summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-x.ci/scripts/linux/docker.sh12
-rw-r--r--.ci/templates/build-msvc.yml2
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt109
-rw-r--r--CMakeModules/DownloadExternals.cmake22
-rw-r--r--dist/icons/overlay/arrow_left.pngbin0 -> 1490 bytes
-rw-r--r--dist/icons/overlay/arrow_left_dark.pngbin0 -> 712 bytes
-rw-r--r--dist/icons/overlay/arrow_right.pngbin0 -> 1394 bytes
-rw-r--r--dist/icons/overlay/arrow_right_dark.pngbin0 -> 683 bytes
-rw-r--r--dist/icons/overlay/button_A.pngbin0 -> 3494 bytes
-rw-r--r--dist/icons/overlay/button_A_dark.pngbin0 -> 3167 bytes
-rw-r--r--dist/icons/overlay/button_B.pngbin0 -> 3375 bytes
-rw-r--r--dist/icons/overlay/button_B_dark.pngbin0 -> 2975 bytes
-rw-r--r--dist/icons/overlay/button_L.pngbin0 -> 796 bytes
-rw-r--r--dist/icons/overlay/button_L_dark.pngbin0 -> 745 bytes
-rw-r--r--dist/icons/overlay/button_R.pngbin0 -> 1841 bytes
-rw-r--r--dist/icons/overlay/button_R_dark.pngbin0 -> 1835 bytes
-rw-r--r--dist/icons/overlay/button_X.pngbin0 -> 3968 bytes
-rw-r--r--dist/icons/overlay/button_X_dark.pngbin0 -> 3530 bytes
-rw-r--r--dist/icons/overlay/button_Y.pngbin0 -> 3337 bytes
-rw-r--r--dist/icons/overlay/button_Y_dark.pngbin0 -> 2883 bytes
-rw-r--r--dist/icons/overlay/button_minus.pngbin0 -> 2401 bytes
-rw-r--r--dist/icons/overlay/button_minus_dark.pngbin0 -> 1969 bytes
-rw-r--r--dist/icons/overlay/button_plus.pngbin0 -> 2497 bytes
-rw-r--r--dist/icons/overlay/button_plus_dark.pngbin0 -> 2066 bytes
-rw-r--r--dist/icons/overlay/button_press_stick.pngbin0 -> 5225 bytes
-rw-r--r--dist/icons/overlay/button_press_stick_dark.pngbin0 -> 3636 bytes
-rw-r--r--dist/icons/overlay/controller_dual_joycon.pngbin0 -> 7312 bytes
-rw-r--r--dist/icons/overlay/controller_dual_joycon_dark.pngbin0 -> 5889 bytes
-rw-r--r--dist/icons/overlay/controller_handheld.pngbin0 -> 4645 bytes
-rw-r--r--dist/icons/overlay/controller_handheld_dark.pngbin0 -> 3745 bytes
-rw-r--r--dist/icons/overlay/controller_pro.pngbin0 -> 9493 bytes
-rw-r--r--dist/icons/overlay/controller_pro_dark.pngbin0 -> 7488 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left.pngbin0 -> 7489 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_a.pngbin0 -> 2609 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_a_dark.pngbin0 -> 2564 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_b.pngbin0 -> 2559 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_b_dark.pngbin0 -> 2383 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_dark.pngbin0 -> 6768 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_x.pngbin0 -> 2541 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_x_dark.pngbin0 -> 2392 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_y.pngbin0 -> 2641 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_y_dark.pngbin0 -> 2639 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_right.pngbin0 -> 7497 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_right_dark.pngbin0 -> 6729 bytes
-rw-r--r--dist/icons/overlay/osk_button_B.pngbin0 -> 741 bytes
-rw-r--r--dist/icons/overlay/osk_button_B_dark.pngbin0 -> 767 bytes
-rw-r--r--dist/icons/overlay/osk_button_B_dark_disabled.pngbin0 -> 781 bytes
-rw-r--r--dist/icons/overlay/osk_button_B_disabled.pngbin0 -> 791 bytes
-rw-r--r--dist/icons/overlay/osk_button_Y.pngbin0 -> 726 bytes
-rw-r--r--dist/icons/overlay/osk_button_Y_dark.pngbin0 -> 502 bytes
-rw-r--r--dist/icons/overlay/osk_button_Y_dark_disabled.pngbin0 -> 694 bytes
-rw-r--r--dist/icons/overlay/osk_button_Y_disabled.pngbin0 -> 699 bytes
-rw-r--r--dist/icons/overlay/osk_button_backspace.pngbin0 -> 2919 bytes
-rw-r--r--dist/icons/overlay/osk_button_backspace_dark.pngbin0 -> 2958 bytes
-rw-r--r--dist/icons/overlay/osk_button_plus.pngbin0 -> 626 bytes
-rw-r--r--dist/icons/overlay/osk_button_plus_dark.pngbin0 -> 676 bytes
-rw-r--r--dist/icons/overlay/osk_button_plus_dark_disabled.pngbin0 -> 645 bytes
-rw-r--r--dist/icons/overlay/osk_button_plus_disabled.pngbin0 -> 664 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift.pngbin0 -> 1876 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_dark.pngbin0 -> 2003 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_lock_off.pngbin0 -> 281 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_lock_on.pngbin0 -> 274 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_on.pngbin0 -> 1573 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_on_dark.pngbin0 -> 1937 bytes
-rw-r--r--dist/icons/overlay/overlay.qrc64
-rw-r--r--dist/qt_themes/default/style.qss377
-rw-r--r--dist/qt_themes/qdarkstyle/style.qss399
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/style.qss439
-rw-r--r--externals/CMakeLists.txt5
m---------externals/SDL0
-rw-r--r--src/audio_core/audio_out.cpp2
-rw-r--r--src/audio_core/audio_renderer.cpp2
-rw-r--r--src/audio_core/cubeb_sink.cpp2
-rw-r--r--src/audio_core/stream.cpp2
-rw-r--r--src/common/CMakeLists.txt4
-rw-r--r--src/common/assert.cpp7
-rw-r--r--src/common/logging/backend.cpp39
-rw-r--r--src/common/logging/backend.h8
-rw-r--r--src/common/logging/filter.cpp4
-rw-r--r--src/common/logging/filter.h4
-rw-r--r--src/common/logging/log.h34
-rw-r--r--src/common/logging/text_formatter.cpp4
-rw-r--r--src/common/logging/text_formatter.h4
-rw-r--r--src/common/settings.cpp (renamed from src/core/settings.cpp)15
-rw-r--r--src/common/settings.h (renamed from src/core/settings.h)15
-rw-r--r--src/common/settings_input.cpp (renamed from src/input_common/settings.cpp)2
-rw-r--r--src/common/settings_input.h (renamed from src/input_common/settings.h)1
-rw-r--r--src/core/CMakeLists.txt5
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp2
-rw-r--r--src/core/core.cpp11
-rw-r--r--src/core/core.h3
-rw-r--r--src/core/crypto/aes_util.cpp6
-rw-r--r--src/core/crypto/aes_util.h8
-rw-r--r--src/core/crypto/key_manager.cpp2
-rw-r--r--src/core/file_sys/patch_manager.cpp2
-rw-r--r--src/core/file_sys/program_metadata.cpp6
-rw-r--r--src/core/file_sys/program_metadata.h9
-rw-r--r--src/core/frontend/applets/profile_select.cpp2
-rw-r--r--src/core/frontend/applets/software_keyboard.cpp148
-rw-r--r--src/core/frontend/applets/software_keyboard.h118
-rw-r--r--src/core/frontend/emu_window.cpp25
-rw-r--r--src/core/frontend/emu_window.h28
-rw-r--r--src/core/frontend/framebuffer_layout.cpp2
-rw-r--r--src/core/frontend/input_interpreter.cpp15
-rw-r--r--src/core/frontend/input_interpreter.h3
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp8
-rw-r--r--src/core/hle/kernel/hle_ipc.h10
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp13
-rw-r--r--src/core/hle/kernel/k_resource_limit.h12
-rw-r--r--src/core/hle/kernel/kernel.cpp7
-rw-r--r--src/core/hle/kernel/process.cpp2
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/core/hle/service/acc/acc.cpp4
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp2
-rw-r--r--src/core/hle/service/am/am.cpp101
-rw-r--r--src/core/hle/service/am/am.h5
-rw-r--r--src/core/hle/service/am/applets/applets.cpp57
-rw-r--r--src/core/hle/service/am/applets/applets.h30
-rw-r--r--src/core/hle/service/am/applets/controller.cpp5
-rw-r--r--src/core/hle/service/am/applets/controller.h3
-rw-r--r--src/core/hle/service/am/applets/error.cpp5
-rw-r--r--src/core/hle/service/am/applets/error.h3
-rw-r--r--src/core/hle/service/am/applets/general_backend.cpp14
-rw-r--r--src/core/hle/service/am/applets/general_backend.h8
-rw-r--r--src/core/hle/service/am/applets/profile_select.cpp4
-rw-r--r--src/core/hle/service/am/applets/profile_select.h2
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp1153
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.h186
-rw-r--r--src/core/hle/service/am/applets/software_keyboard_types.h295
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp5
-rw-r--r--src/core/hle/service/am/applets/web_browser.h3
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp2
-rw-r--r--src/core/hle/service/apm/controller.cpp2
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp2
-rw-r--r--src/core/hle/service/bcat/module.cpp2
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp2
-rw-r--r--src/core/hle/service/glue/arp.cpp10
-rw-r--r--src/core/hle/service/glue/ectx.cpp22
-rw-r--r--src/core/hle/service/glue/ectx.h21
-rw-r--r--src/core/hle/service/glue/glue.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h2
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h2
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h2
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/npad.h3
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp41
-rw-r--r--src/core/hle/service/lbl/lbl.cpp2
-rw-r--r--src/core/hle/service/lm/lm.cpp13
-rw-r--r--src/core/hle/service/nfc/nfc.cpp2
-rw-r--r--src/core/hle/service/nifm/nifm.cpp2
-rw-r--r--src/core/hle/service/ns/ns.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp14
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp12
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp2
-rw-r--r--src/core/hle/service/service.cpp2
-rw-r--r--src/core/hle/service/set/set.cpp5
-rw-r--r--src/core/hle/service/spl/module.cpp2
-rw-r--r--src/core/hle/service/time/time.cpp8
-rw-r--r--src/core/hle/service/time/time_manager.cpp2
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp2
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp6
-rw-r--r--src/core/hle/service/vi/vi.cpp10
-rw-r--r--src/core/loader/kip.cpp3
-rw-r--r--src/core/loader/nro.cpp2
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/core/perf_stats.cpp2
-rw-r--r--src/core/reporter.cpp2
-rw-r--r--src/core/telemetry_session.cpp2
-rw-r--r--src/input_common/CMakeLists.txt4
-rwxr-xr-xsrc/input_common/analog_from_button.cpp2
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp2
-rw-r--r--src/input_common/mouse/mouse_input.cpp2
-rw-r--r--src/input_common/mouse/mouse_poller.cpp2
-rw-r--r--src/input_common/sdl/sdl_impl.cpp38
-rw-r--r--src/input_common/sdl/sdl_impl.h4
-rw-r--r--src/input_common/touch_from_button.cpp2
-rw-r--r--src/input_common/udp/client.cpp2
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h2
-rw-r--r--src/video_core/engines/maxwell_dma.cpp2
-rw-r--r--src/video_core/gpu.cpp12
-rw-r--r--src/video_core/gpu.h3
-rw-r--r--src/video_core/gpu_thread.cpp2
-rw-r--r--src/video_core/macro/macro.cpp2
-rw-r--r--src/video_core/query_cache.h2
-rw-r--r--src/video_core/renderer_base.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp2
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp25
-rw-r--r--src/video_core/texture_cache/image_view_base.cpp2
-rw-r--r--src/video_core/texture_cache/util.cpp2
-rw-r--r--src/video_core/textures/texture.cpp2
-rw-r--r--src/video_core/video_core.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp2
-rw-r--r--src/yuzu/CMakeLists.txt4
-rw-r--r--src/yuzu/applets/error.cpp22
-rw-r--r--src/yuzu/applets/error.h2
-rw-r--r--src/yuzu/applets/software_keyboard.cpp1712
-rw-r--r--src/yuzu/applets/software_keyboard.h283
-rw-r--r--src/yuzu/applets/software_keyboard.ui3503
-rw-r--r--src/yuzu/bootmanager.cpp2
-rw-r--r--src/yuzu/configuration/config.cpp24
-rw-r--r--src/yuzu/configuration/config.h4
-rw-r--r--src/yuzu/configuration/configuration_shared.cpp2
-rw-r--r--src/yuzu/configuration/configuration_shared.h2
-rw-r--r--src/yuzu/configuration/configure_audio.cpp2
-rw-r--r--src/yuzu/configuration/configure_cpu.cpp2
-rw-r--r--src/yuzu/configuration/configure_cpu.h2
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.cpp2
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.h2
-rw-r--r--src/yuzu/configuration/configure_debug.cpp8
-rw-r--r--src/yuzu/configuration/configure_debug.ui7
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp4
-rw-r--r--src/yuzu/configuration/configure_filesystem.cpp2
-rw-r--r--src/yuzu/configuration/configure_general.cpp2
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp2
-rw-r--r--src/yuzu/configuration/configure_graphics.h2
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_player.h2
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.h2
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp2
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp2
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp4
-rw-r--r--src/yuzu/configuration/configure_service.cpp2
-rw-r--r--src/yuzu/configuration/configure_system.cpp4
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.cpp2
-rw-r--r--src/yuzu/configuration/configure_ui.cpp4
-rw-r--r--src/yuzu/configuration/configure_vibration.cpp2
-rw-r--r--src/yuzu/configuration/configure_web.cpp2
-rw-r--r--src/yuzu/debugger/console.cpp8
-rw-r--r--src/yuzu/debugger/controller.cpp2
-rw-r--r--src/yuzu/main.cpp203
-rw-r--r--src/yuzu/main.h35
-rw-r--r--src/yuzu/util/overlay_dialog.cpp249
-rw-r--r--src/yuzu/util/overlay_dialog.h107
-rw-r--r--src/yuzu/util/overlay_dialog.ui404
-rw-r--r--src/yuzu_cmd/CMakeLists.txt1
-rw-r--r--src/yuzu_cmd/config.cpp16
-rw-r--r--src/yuzu_cmd/default_ini.h6
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp11
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.h2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp12
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp10
-rw-r--r--src/yuzu_cmd/resource.h16
-rw-r--r--src/yuzu_cmd/yuzu.cpp10
257 files changed, 10099 insertions, 903 deletions
diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh
index 39b1f77d7..1af5ded3d 100755
--- a/.ci/scripts/linux/docker.sh
+++ b/.ci/scripts/linux/docker.sh
@@ -8,7 +8,17 @@ cd /yuzu
ccache -s
mkdir build || true && cd build
-cmake .. -DDISPLAY_VERSION=$1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_INSTALL_PREFIX="/usr"
+cmake .. \
+ -DBoost_USE_STATIC_LIBS=ON \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
+ -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
+ -DCMAKE_INSTALL_PREFIX="/usr" \
+ -DDISPLAY_VERSION=$1 \
+ -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
+ -DENABLE_QT_TRANSLATION=ON \
+ -DUSE_DISCORD_PRESENCE=ON \
+ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"}
make -j$(nproc)
diff --git a/.ci/templates/build-msvc.yml b/.ci/templates/build-msvc.yml
index 097367018..74e688c12 100644
--- a/.ci/templates/build-msvc.yml
+++ b/.ci/templates/build-msvc.yml
@@ -8,7 +8,7 @@ steps:
displayName: 'Install vulkan-sdk'
- script: python -m pip install --upgrade pip conan
displayName: 'Install conan'
-- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cmake --install . --config Release && cd ..
+- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cmake --install . --config Release && cd ..
displayName: 'Configure CMake'
- task: MSBuild@1
displayName: 'Build'
diff --git a/.gitmodules b/.gitmodules
index a0a89933d..8e5bc4581 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -40,3 +40,6 @@
[submodule "ffmpeg"]
path = externals/ffmpeg
url = https://git.ffmpeg.org/ffmpeg.git
+[submodule "SDL"]
+ path = externals/SDL
+ url = https://github.com/libsdl-org/SDL.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ea6c650e..15ecb8a9c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,6 +11,7 @@ project(yuzu)
# Set bundled sdl2/qt as dependent options.
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
+CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
option(ENABLE_QT "Enable the Qt frontend" ON)
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
@@ -18,7 +19,9 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "EN
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
-CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled yuzu" ON "WIN32" OFF)
+option(YUZU_USE_BUNDLED_BOOST "Download bundled Boost" OFF)
+
+CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" ON "WIN32" OFF)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
@@ -166,8 +169,6 @@ macro(yuzu_find_packages)
# Cmake Pkg Prefix Version Conan Pkg
"Catch2 2.13 catch2/2.13.0"
"fmt 7.1 fmt/7.1.2"
- # can't use until https://github.com/bincrafters/community/issues/1173
- #"libzip 1.5 libzip/1.5.2@bincrafters/stable"
"lz4 1.8 lz4/1.9.2"
"nlohmann_json 3.8 nlohmann_json/3.8.0"
"ZLIB 1.2 zlib/1.2.11"
@@ -200,7 +201,9 @@ macro(yuzu_find_packages)
unset(FN_FORCE_REQUIRED)
endmacro()
-find_package(Boost 1.73.0 COMPONENTS context headers QUIET)
+if (NOT YUZU_USE_BUNDLED_BOOST)
+ find_package(Boost 1.73.0 COMPONENTS context headers QUIET)
+endif()
if (Boost_FOUND)
set(Boost_LIBRARIES Boost::boost)
# Conditionally add Boost::context only if the active version of the Conan or system Boost package provides it
@@ -211,6 +214,20 @@ if (Boost_FOUND)
if (TARGET Boost::context)
list(APPEND Boost_LIBRARIES Boost::context)
endif()
+elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR YUZU_USE_BUNDLED_BOOST)
+ message(STATUS "Boost 1.73.0 or newer not found, falling back to externals")
+ set(YUZU_USE_BUNDLED_BOOST ON CACHE BOOL "Download bundled Boost" FORCE)
+
+ # Use yuzu Boost binaries
+ set(Boost_EXT_NAME "boost_1_75_0")
+ set(Boost_PATH "${CMAKE_BINARY_DIR}/externals/${Boost_EXT_NAME}")
+ download_bundled_external("boost/" ${Boost_EXT_NAME} "")
+ set(Boost_USE_DEBUG_RUNTIME FALSE)
+ set(Boost_USE_STATIC_LIBS ON)
+ find_package(Boost 1.75.0 REQUIRED COMPONENTS context headers PATHS ${Boost_PATH} NO_DEFAULT_PATH)
+ # Manually set the include dirs since the find_package sets it incorrectly
+ set(Boost_INCLUDE_DIRS ${Boost_PATH}/include CACHE PATH "Path to Boost headers" FORCE)
+ include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
else()
message(STATUS "Boost 1.73.0 or newer not found, falling back to Conan")
list(APPEND CONAN_REQUIRED_LIBS "boost/1.73.0")
@@ -251,21 +268,45 @@ if(ENABLE_QT)
if (ENABLE_QT_TRANSLATION)
find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT})
endif()
- if (NOT Qt5_FOUND)
- list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable")
- endif()
endif()
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package
-if(ENABLE_SDL2)
- if(EXISTS ${CMAKE_BINARY_DIR}/sdl2Config.cmake)
- include(${CMAKE_BINARY_DIR}/sdl2Config.cmake)
- list(APPEND CMAKE_MODULE_PATH "${CONAN_SDL2_ROOT_RELEASE}")
- list(APPEND CMAKE_PREFIX_PATH "${CONAN_SDL2_ROOT_RELEASE}")
- endif()
- find_package(SDL2)
- if (NOT SDL2_FOUND)
- # otherwise add this to the list of libraries to install
- list(APPEND CONAN_REQUIRED_LIBS "sdl2/2.0.14@bincrafters/stable")
+if (ENABLE_SDL2)
+ if (YUZU_USE_BUNDLED_SDL2)
+ # Detect toolchain and platform
+ if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
+ set(SDL2_VER "SDL2-2.0.14")
+ else()
+ message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.")
+ endif()
+
+ if (DEFINED SDL2_VER)
+ download_bundled_external("sdl2/" ${SDL2_VER} SDL2_PREFIX)
+ endif()
+
+ set(SDL2_FOUND YES)
+ set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers")
+ set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library")
+ set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll")
+
+ add_library(SDL2 INTERFACE)
+ target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}")
+ target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
+ else()
+ find_package(SDL2 2.0.14 QUIET)
+
+ if (SDL2_FOUND)
+ # Some installations don't set SDL2_LIBRARIES
+ if("${SDL2_LIBRARIES}" STREQUAL "")
+ message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
+ set(SDL2_LIBRARIES "SDL2::SDL2")
+ endif()
+
+ include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
+ add_library(SDL2 INTERFACE)
+ target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
+ else()
+ message(STATUS "SDL2 2.0.14 or newer not found, falling back to externals.")
+ endif()
endif()
endif()
@@ -287,9 +328,6 @@ if (CONAN_REQUIRED_LIBS)
)
conan_check(VERSION 1.24.0 REQUIRED)
- # Add the bincrafters remote
- conan_add_remote(NAME bincrafters
- URL https://api.bintray.com/conan/bincrafters/public-conan)
# Manually add iconv to fix a dep conflict between qt and sdl2
# We don't need to add it through find_package or anything since the other two can find it just fine
@@ -340,11 +378,6 @@ if (CONAN_REQUIRED_LIBS)
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
endif()
endif()
- if(ENABLE_SDL2)
- list(APPEND CMAKE_MODULE_PATH "${CONAN_SDL2_ROOT_RELEASE}")
- list(APPEND CMAKE_PREFIX_PATH "${CONAN_SDL2_ROOT_RELEASE}")
- find_package(SDL2 REQUIRED)
- endif()
endif()
@@ -360,23 +393,6 @@ elseif (TARGET Boost::boost)
add_library(boost ALIAS Boost::boost)
endif()
-if (TARGET sdl2::sdl2)
- # imported from the conan generated sdl2Config.cmake
- set_target_properties(sdl2::sdl2 PROPERTIES IMPORTED_GLOBAL TRUE)
- add_library(SDL2 ALIAS sdl2::sdl2)
-elseif(SDL2_FOUND)
- # found through the system package manager
- # Some installations don't set SDL2_LIBRARIES
- if("${SDL2_LIBRARIES}" STREQUAL "")
- message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
- set(SDL2_LIBRARIES "SDL2::SDL2")
- endif()
-
- include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
- add_library(SDL2 INTERFACE)
- target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
-endif()
-
# Ensure libusb is properly configured (based on dolphin libusb include)
if(NOT APPLE)
include(FindPkgConfig)
@@ -396,7 +412,7 @@ set(FFmpeg_COMPONENTS
if (NOT YUZU_USE_BUNDLED_FFMPEG)
# Use system installed FFmpeg
- find_package(FFmpeg REQUIRED COMPONENTS ${FFmpeg_COMPONENTS})
+ find_package(FFmpeg QUIET COMPONENTS ${FFmpeg_COMPONENTS})
if (FFmpeg_FOUND)
# Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries.
@@ -435,6 +451,7 @@ if (YUZU_USE_BUNDLED_FFMPEG)
set(FFmpeg_FOUND YES)
endif()
+ unset(FFmpeg_LIBRARIES CACHE)
foreach(COMPONENT ${FFmpeg_COMPONENTS})
set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
@@ -447,7 +464,7 @@ if (YUZU_USE_BUNDLED_FFMPEG)
endforeach()
set(FFmpeg_INCLUDE_DIR
- ${FFmpeg_PREFIX}
+ "${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR}"
CACHE PATH "Path to FFmpeg headers" FORCE)
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
@@ -494,13 +511,11 @@ if (YUZU_USE_BUNDLED_FFMPEG)
# ALL makes this custom target build every time
# but it won't actually build if the DEPENDS parameter is up to date
- add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_LIBRARIES})
add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
+ add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_LIBRARIES} ffmpeg-configure)
if (FFmpeg_FOUND)
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
-
- add_dependencies(ffmpeg-build ffmpeg-configure)
else()
message(FATAL_ERROR "FFmpeg not found")
endif()
diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake
index d3f91764d..4c4dec5ff 100644
--- a/CMakeModules/DownloadExternals.cmake
+++ b/CMakeModules/DownloadExternals.cmake
@@ -4,15 +4,29 @@
# remote_path: path to the file to download, relative to the remote repository root
# prefix_var: name of a variable which will be set with the path to the extracted contents
function(download_bundled_external remote_path lib_name prefix_var)
+
+set(package_repo "no_platform")
+set(package_extension "no_platform")
+if (WIN32)
+ set(package_repo "ext-windows-bin/raw/master/")
+ set(package_extension ".7z")
+elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ set(package_repo "ext-linux-bin/raw/main/")
+ set(package_extension ".tar.xz")
+else()
+ message(FATAL_ERROR "No package available for this platform")
+endif()
+set(package_url "https://github.com/yuzu-emu/${package_repo}")
+
set(prefix "${CMAKE_BINARY_DIR}/externals/${lib_name}")
if (NOT EXISTS "${prefix}")
message(STATUS "Downloading binaries for ${lib_name}...")
file(DOWNLOAD
- https://github.com/yuzu-emu/ext-windows-bin/raw/master/${remote_path}${lib_name}.7z
- "${CMAKE_BINARY_DIR}/externals/${lib_name}.7z" SHOW_PROGRESS)
- execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/externals/${lib_name}.7z"
+ ${package_url}${remote_path}${lib_name}${package_extension}
+ "${CMAKE_BINARY_DIR}/externals/${lib_name}${package_extension}" SHOW_PROGRESS)
+ execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/externals/${lib_name}${package_extension}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
endif()
message(STATUS "Using bundled binaries at ${prefix}")
set(${prefix_var} "${prefix}" PARENT_SCOPE)
-endfunction() \ No newline at end of file
+endfunction()
diff --git a/dist/icons/overlay/arrow_left.png b/dist/icons/overlay/arrow_left.png
new file mode 100644
index 000000000..a5d4fecfe
--- /dev/null
+++ b/dist/icons/overlay/arrow_left.png
Binary files differ
diff --git a/dist/icons/overlay/arrow_left_dark.png b/dist/icons/overlay/arrow_left_dark.png
new file mode 100644
index 000000000..f73672a59
--- /dev/null
+++ b/dist/icons/overlay/arrow_left_dark.png
Binary files differ
diff --git a/dist/icons/overlay/arrow_right.png b/dist/icons/overlay/arrow_right.png
new file mode 100644
index 000000000..e47ee94bd
--- /dev/null
+++ b/dist/icons/overlay/arrow_right.png
Binary files differ
diff --git a/dist/icons/overlay/arrow_right_dark.png b/dist/icons/overlay/arrow_right_dark.png
new file mode 100644
index 000000000..91cf83d2c
--- /dev/null
+++ b/dist/icons/overlay/arrow_right_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_A.png b/dist/icons/overlay/button_A.png
new file mode 100644
index 000000000..fd90f8b42
--- /dev/null
+++ b/dist/icons/overlay/button_A.png
Binary files differ
diff --git a/dist/icons/overlay/button_A_dark.png b/dist/icons/overlay/button_A_dark.png
new file mode 100644
index 000000000..d6b5514fa
--- /dev/null
+++ b/dist/icons/overlay/button_A_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_B.png b/dist/icons/overlay/button_B.png
new file mode 100644
index 000000000..e8927addc
--- /dev/null
+++ b/dist/icons/overlay/button_B.png
Binary files differ
diff --git a/dist/icons/overlay/button_B_dark.png b/dist/icons/overlay/button_B_dark.png
new file mode 100644
index 000000000..3acbeddcd
--- /dev/null
+++ b/dist/icons/overlay/button_B_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_L.png b/dist/icons/overlay/button_L.png
new file mode 100644
index 000000000..77838369e
--- /dev/null
+++ b/dist/icons/overlay/button_L.png
Binary files differ
diff --git a/dist/icons/overlay/button_L_dark.png b/dist/icons/overlay/button_L_dark.png
new file mode 100644
index 000000000..c96a5e868
--- /dev/null
+++ b/dist/icons/overlay/button_L_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_R.png b/dist/icons/overlay/button_R.png
new file mode 100644
index 000000000..4e5553954
--- /dev/null
+++ b/dist/icons/overlay/button_R.png
Binary files differ
diff --git a/dist/icons/overlay/button_R_dark.png b/dist/icons/overlay/button_R_dark.png
new file mode 100644
index 000000000..ed13199c4
--- /dev/null
+++ b/dist/icons/overlay/button_R_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_X.png b/dist/icons/overlay/button_X.png
new file mode 100644
index 000000000..fe70fb685
--- /dev/null
+++ b/dist/icons/overlay/button_X.png
Binary files differ
diff --git a/dist/icons/overlay/button_X_dark.png b/dist/icons/overlay/button_X_dark.png
new file mode 100644
index 000000000..b2c83d0c1
--- /dev/null
+++ b/dist/icons/overlay/button_X_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_Y.png b/dist/icons/overlay/button_Y.png
new file mode 100644
index 000000000..ca0de569d
--- /dev/null
+++ b/dist/icons/overlay/button_Y.png
Binary files differ
diff --git a/dist/icons/overlay/button_Y_dark.png b/dist/icons/overlay/button_Y_dark.png
new file mode 100644
index 000000000..0f3e4df25
--- /dev/null
+++ b/dist/icons/overlay/button_Y_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_minus.png b/dist/icons/overlay/button_minus.png
new file mode 100644
index 000000000..7b315fe79
--- /dev/null
+++ b/dist/icons/overlay/button_minus.png
Binary files differ
diff --git a/dist/icons/overlay/button_minus_dark.png b/dist/icons/overlay/button_minus_dark.png
new file mode 100644
index 000000000..6dfcdc1b5
--- /dev/null
+++ b/dist/icons/overlay/button_minus_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_plus.png b/dist/icons/overlay/button_plus.png
new file mode 100644
index 000000000..4d8090d7d
--- /dev/null
+++ b/dist/icons/overlay/button_plus.png
Binary files differ
diff --git a/dist/icons/overlay/button_plus_dark.png b/dist/icons/overlay/button_plus_dark.png
new file mode 100644
index 000000000..abe8b9c95
--- /dev/null
+++ b/dist/icons/overlay/button_plus_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_press_stick.png b/dist/icons/overlay/button_press_stick.png
new file mode 100644
index 000000000..6d0254d50
--- /dev/null
+++ b/dist/icons/overlay/button_press_stick.png
Binary files differ
diff --git a/dist/icons/overlay/button_press_stick_dark.png b/dist/icons/overlay/button_press_stick_dark.png
new file mode 100644
index 000000000..757d0ab29
--- /dev/null
+++ b/dist/icons/overlay/button_press_stick_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_dual_joycon.png b/dist/icons/overlay/controller_dual_joycon.png
new file mode 100644
index 000000000..8e8b5ad41
--- /dev/null
+++ b/dist/icons/overlay/controller_dual_joycon.png
Binary files differ
diff --git a/dist/icons/overlay/controller_dual_joycon_dark.png b/dist/icons/overlay/controller_dual_joycon_dark.png
new file mode 100644
index 000000000..63e03eb4e
--- /dev/null
+++ b/dist/icons/overlay/controller_dual_joycon_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_handheld.png b/dist/icons/overlay/controller_handheld.png
new file mode 100644
index 000000000..deb375011
--- /dev/null
+++ b/dist/icons/overlay/controller_handheld.png
Binary files differ
diff --git a/dist/icons/overlay/controller_handheld_dark.png b/dist/icons/overlay/controller_handheld_dark.png
new file mode 100644
index 000000000..1f5317aa0
--- /dev/null
+++ b/dist/icons/overlay/controller_handheld_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_pro.png b/dist/icons/overlay/controller_pro.png
new file mode 100644
index 000000000..67cf86d5c
--- /dev/null
+++ b/dist/icons/overlay/controller_pro.png
Binary files differ
diff --git a/dist/icons/overlay/controller_pro_dark.png b/dist/icons/overlay/controller_pro_dark.png
new file mode 100644
index 000000000..7be655b96
--- /dev/null
+++ b/dist/icons/overlay/controller_pro_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left.png b/dist/icons/overlay/controller_single_joycon_left.png
new file mode 100644
index 000000000..340ddc71b
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_a.png b/dist/icons/overlay/controller_single_joycon_left_a.png
new file mode 100644
index 000000000..e0f5c2ad4
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_a.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_a_dark.png b/dist/icons/overlay/controller_single_joycon_left_a_dark.png
new file mode 100644
index 000000000..53e04781e
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_a_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_b.png b/dist/icons/overlay/controller_single_joycon_left_b.png
new file mode 100644
index 000000000..7429450a3
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_b.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_b_dark.png b/dist/icons/overlay/controller_single_joycon_left_b_dark.png
new file mode 100644
index 000000000..3bd97a8eb
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_b_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_dark.png b/dist/icons/overlay/controller_single_joycon_left_dark.png
new file mode 100644
index 000000000..24ed2c44c
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_x.png b/dist/icons/overlay/controller_single_joycon_left_x.png
new file mode 100644
index 000000000..4615172a3
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_x.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_x_dark.png b/dist/icons/overlay/controller_single_joycon_left_x_dark.png
new file mode 100644
index 000000000..119e3091a
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_x_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_y.png b/dist/icons/overlay/controller_single_joycon_left_y.png
new file mode 100644
index 000000000..24421d8b9
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_y.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_y_dark.png b/dist/icons/overlay/controller_single_joycon_left_y_dark.png
new file mode 100644
index 000000000..fdf177c12
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_y_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_right.png b/dist/icons/overlay/controller_single_joycon_right.png
new file mode 100644
index 000000000..5b8fc0eff
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_right.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_right_dark.png b/dist/icons/overlay/controller_single_joycon_right_dark.png
new file mode 100644
index 000000000..afa80e6ef
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_right_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_B.png b/dist/icons/overlay/osk_button_B.png
new file mode 100644
index 000000000..f4a041178
--- /dev/null
+++ b/dist/icons/overlay/osk_button_B.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_B_dark.png b/dist/icons/overlay/osk_button_B_dark.png
new file mode 100644
index 000000000..2d2bffcca
--- /dev/null
+++ b/dist/icons/overlay/osk_button_B_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_B_dark_disabled.png b/dist/icons/overlay/osk_button_B_dark_disabled.png
new file mode 100644
index 000000000..93c102b1b
--- /dev/null
+++ b/dist/icons/overlay/osk_button_B_dark_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_B_disabled.png b/dist/icons/overlay/osk_button_B_disabled.png
new file mode 100644
index 000000000..5900982f6
--- /dev/null
+++ b/dist/icons/overlay/osk_button_B_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_Y.png b/dist/icons/overlay/osk_button_Y.png
new file mode 100644
index 000000000..b08b4e26b
--- /dev/null
+++ b/dist/icons/overlay/osk_button_Y.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_Y_dark.png b/dist/icons/overlay/osk_button_Y_dark.png
new file mode 100644
index 000000000..1fba9ca93
--- /dev/null
+++ b/dist/icons/overlay/osk_button_Y_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_Y_dark_disabled.png b/dist/icons/overlay/osk_button_Y_dark_disabled.png
new file mode 100644
index 000000000..6ce53f9e4
--- /dev/null
+++ b/dist/icons/overlay/osk_button_Y_dark_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_Y_disabled.png b/dist/icons/overlay/osk_button_Y_disabled.png
new file mode 100644
index 000000000..25db07f66
--- /dev/null
+++ b/dist/icons/overlay/osk_button_Y_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_backspace.png b/dist/icons/overlay/osk_button_backspace.png
new file mode 100644
index 000000000..4ad284720
--- /dev/null
+++ b/dist/icons/overlay/osk_button_backspace.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_backspace_dark.png b/dist/icons/overlay/osk_button_backspace_dark.png
new file mode 100644
index 000000000..19ac8847e
--- /dev/null
+++ b/dist/icons/overlay/osk_button_backspace_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_plus.png b/dist/icons/overlay/osk_button_plus.png
new file mode 100644
index 000000000..5baa5201e
--- /dev/null
+++ b/dist/icons/overlay/osk_button_plus.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_plus_dark.png b/dist/icons/overlay/osk_button_plus_dark.png
new file mode 100644
index 000000000..4cadb438b
--- /dev/null
+++ b/dist/icons/overlay/osk_button_plus_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_plus_dark_disabled.png b/dist/icons/overlay/osk_button_plus_dark_disabled.png
new file mode 100644
index 000000000..b8eb8dc3d
--- /dev/null
+++ b/dist/icons/overlay/osk_button_plus_dark_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_plus_disabled.png b/dist/icons/overlay/osk_button_plus_disabled.png
new file mode 100644
index 000000000..c23e9d95d
--- /dev/null
+++ b/dist/icons/overlay/osk_button_plus_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift.png b/dist/icons/overlay/osk_button_shift.png
new file mode 100644
index 000000000..f03e30697
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_dark.png b/dist/icons/overlay/osk_button_shift_dark.png
new file mode 100644
index 000000000..c9cc5cd9a
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_lock_off.png b/dist/icons/overlay/osk_button_shift_lock_off.png
new file mode 100644
index 000000000..585500b3a
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_lock_off.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_lock_on.png b/dist/icons/overlay/osk_button_shift_lock_on.png
new file mode 100644
index 000000000..09077ab01
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_lock_on.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_on.png b/dist/icons/overlay/osk_button_shift_on.png
new file mode 100644
index 000000000..e7c1187f9
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_on.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_on_dark.png b/dist/icons/overlay/osk_button_shift_on_dark.png
new file mode 100644
index 000000000..58e0d9cf4
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_on_dark.png
Binary files differ
diff --git a/dist/icons/overlay/overlay.qrc b/dist/icons/overlay/overlay.qrc
new file mode 100644
index 000000000..d5a21ce10
--- /dev/null
+++ b/dist/icons/overlay/overlay.qrc
@@ -0,0 +1,64 @@
+<RCC>
+ <qresource prefix="overlay">
+ <file>arrow_left.png</file>
+ <file>arrow_left_dark.png</file>
+ <file>arrow_right.png</file>
+ <file>arrow_right_dark.png</file>
+ <file>button_minus.png</file>
+ <file>button_minus_dark.png</file>
+ <file>button_plus.png</file>
+ <file>button_plus_dark.png</file>
+ <file>button_A.png</file>
+ <file>button_A_dark.png</file>
+ <file>button_B.png</file>
+ <file>button_B_dark.png</file>
+ <file>button_X.png</file>
+ <file>button_X_dark.png</file>
+ <file>button_Y.png</file>
+ <file>button_Y_dark.png</file>
+ <file>button_L.png</file>
+ <file>button_L_dark.png</file>
+ <file>button_R.png</file>
+ <file>button_R_dark.png</file>
+ <file>button_press_stick.png</file>
+ <file>button_press_stick_dark.png</file>
+ <file>osk_button_B.png</file>
+ <file>osk_button_B_disabled.png</file>
+ <file>osk_button_B_dark.png</file>
+ <file>osk_button_B_dark_disabled.png</file>
+ <file>osk_button_Y.png</file>
+ <file>osk_button_Y_disabled.png</file>
+ <file>osk_button_Y_dark.png</file>
+ <file>osk_button_Y_dark_disabled.png</file>
+ <file>osk_button_backspace.png</file>
+ <file>osk_button_backspace_dark.png</file>
+ <file>osk_button_plus.png</file>
+ <file>osk_button_plus_disabled.png</file>
+ <file>osk_button_plus_dark.png</file>
+ <file>osk_button_plus_dark_disabled.png</file>
+ <file>osk_button_shift.png</file>
+ <file>osk_button_shift_dark.png</file>
+ <file>osk_button_shift_on.png</file>
+ <file>osk_button_shift_on_dark.png</file>
+ <file>osk_button_shift_lock_on.png</file>
+ <file>osk_button_shift_lock_off.png</file>
+ <file>controller_dual_joycon.png</file>
+ <file>controller_dual_joycon_dark.png</file>
+ <file>controller_pro.png</file>
+ <file>controller_pro_dark.png</file>
+ <file>controller_handheld.png</file>
+ <file>controller_handheld_dark.png</file>
+ <file>controller_single_joycon_left.png</file>
+ <file>controller_single_joycon_left_dark.png</file>
+ <file>controller_single_joycon_right.png</file>
+ <file>controller_single_joycon_right_dark.png</file>
+ <file>controller_single_joycon_left_a.png</file>
+ <file>controller_single_joycon_left_a_dark.png</file>
+ <file>controller_single_joycon_left_b.png</file>
+ <file>controller_single_joycon_left_b_dark.png</file>
+ <file>controller_single_joycon_left_x.png</file>
+ <file>controller_single_joycon_left_x_dark.png</file>
+ <file>controller_single_joycon_left_y.png</file>
+ <file>controller_single_joycon_left_y_dark.png</file>
+ </qresource>
+</RCC>
diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss
index 836dd25ca..3bc92b69d 100644
--- a/dist/qt_themes/default/style.qss
+++ b/dist/qt_themes/default/style.qss
@@ -281,3 +281,380 @@ 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 2a1e8ddeb..8ce6d75f7 100644
--- a/dist/qt_themes/qdarkstyle/style.qss
+++ b/dist/qt_themes/qdarkstyle/style.qss
@@ -1560,7 +1560,400 @@ QWidget#controllerPlayer8 {
background: transparent;
}
-/* touchscreen mapping widget */
-TouchScreenPreview {
- qproperty-dotHighlightColor: #3daee9;
+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;
}
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
index a64037455..64e1ecbcc 100644
--- 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,3 +2483,404 @@ 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/externals/CMakeLists.txt b/externals/CMakeLists.txt
index 891a47c3c..e044d9730 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -45,6 +45,11 @@ target_include_directories(microprofile INTERFACE ./microprofile)
add_library(unicorn-headers INTERFACE)
target_include_directories(unicorn-headers INTERFACE ./unicorn/include)
+# SDL2
+if (NOT SDL2_FOUND AND ENABLE_SDL2)
+ add_subdirectory(SDL EXCLUDE_FROM_ALL)
+endif()
+
# SoundTouch
add_subdirectory(soundtouch)
diff --git a/externals/SDL b/externals/SDL
new file mode 160000
+Subproject 4cd981609b50ed273d80c635c1ca4c1e5518fb2
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp
index fe3a898ad..20a756dce 100644
--- a/src/audio_core/audio_out.cpp
+++ b/src/audio_core/audio_out.cpp
@@ -7,7 +7,7 @@
#include "audio_core/sink_details.h"
#include "common/assert.h"
#include "common/logging/log.h"
-#include "core/settings.h"
+#include "common/settings.h"
namespace AudioCore {
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index d2ce8c814..ae2201c36 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -11,8 +11,8 @@
#include "audio_core/info_updater.h"
#include "audio_core/voice_context.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/memory.h"
-#include "core/settings.h"
namespace {
[[nodiscard]] static constexpr s16 ClampToS16(s32 value) {
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp
index 043447eaa..93c35e785 100644
--- a/src/audio_core/cubeb_sink.cpp
+++ b/src/audio_core/cubeb_sink.cpp
@@ -11,7 +11,7 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/ring_buffer.h"
-#include "core/settings.h"
+#include "common/settings.h"
#ifdef _WIN32
#include <objbase.h>
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index b0f6f0c34..ad6c587c2 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -11,8 +11,8 @@
#include "audio_core/stream.h"
#include "common/assert.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core_timing.h"
-#include "core/settings.h"
namespace AudioCore {
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 9f8dafa3b..88644eeb6 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -152,6 +152,10 @@ add_library(common STATIC
scm_rev.cpp
scm_rev.h
scope_exit.h
+ settings.cpp
+ settings.h
+ settings_input.cpp
+ settings_input.h
spin_lock.cpp
spin_lock.h
stream.cpp
diff --git a/src/common/assert.cpp b/src/common/assert.cpp
index d7d91b96b..72f1121aa 100644
--- a/src/common/assert.cpp
+++ b/src/common/assert.cpp
@@ -3,9 +3,12 @@
// Refer to the license.txt file included.
#include "common/assert.h"
-
#include "common/common_funcs.h"
+#include "common/settings.h"
+
void assert_handle_failure() {
- Crash();
+ if (Settings::values.use_debug_asserts) {
+ Crash();
+ }
}
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 4575df24d..96efa977d 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -21,11 +21,11 @@
#include "common/logging/backend.h"
#include "common/logging/log.h"
#include "common/logging/text_formatter.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "common/threadsafe_queue.h"
-#include "core/settings.h"
-namespace Log {
+namespace Common::Log {
/**
* Static state as a singleton.
@@ -37,8 +37,11 @@ public:
return backend;
}
- Impl(Impl const&) = delete;
- const Impl& operator=(Impl const&) = delete;
+ Impl(const Impl&) = delete;
+ Impl& operator=(const Impl&) = delete;
+
+ Impl(Impl&&) = delete;
+ Impl& operator=(Impl&&) = delete;
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
const char* function, std::string message) {
@@ -53,10 +56,10 @@ public:
void RemoveBackend(std::string_view backend_name) {
std::lock_guard lock{writing_mutex};
- const auto it =
- std::remove_if(backends.begin(), backends.end(),
- [&backend_name](const auto& i) { return backend_name == i->GetName(); });
- backends.erase(it, backends.end());
+
+ std::erase_if(backends, [&backend_name](const auto& backend) {
+ return backend_name == backend->GetName();
+ });
}
const Filter& GetGlobalFilter() const {
@@ -132,7 +135,7 @@ private:
std::mutex writing_mutex;
std::thread backend_thread;
std::vector<std::unique_ptr<Backend>> backends;
- Common::MPSCQueue<Log::Entry> message_queue;
+ MPSCQueue<Entry> message_queue;
Filter filter;
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
};
@@ -145,17 +148,19 @@ void ColorConsoleBackend::Write(const Entry& entry) {
PrintColoredMessage(entry);
}
-FileBackend::FileBackend(const std::string& filename) : bytes_written(0) {
- if (Common::FS::Exists(filename + ".old.txt")) {
- Common::FS::Delete(filename + ".old.txt");
+FileBackend::FileBackend(const std::string& filename) {
+ const auto old_filename = filename + ".old.txt";
+
+ if (FS::Exists(old_filename)) {
+ FS::Delete(old_filename);
}
- if (Common::FS::Exists(filename)) {
- Common::FS::Rename(filename, filename + ".old.txt");
+ if (FS::Exists(filename)) {
+ FS::Rename(filename, old_filename);
}
// _SH_DENYWR allows read only access to the file for other programs.
// It is #defined to 0 on other platforms
- file = Common::FS::IOFile(filename, "w", _SH_DENYWR);
+ file = FS::IOFile(filename, "w", _SH_DENYWR);
}
void FileBackend::Write(const Entry& entry) {
@@ -182,7 +187,7 @@ void FileBackend::Write(const Entry& entry) {
void DebuggerBackend::Write(const Entry& entry) {
#ifdef _WIN32
- ::OutputDebugStringW(Common::UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
+ ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
#endif
}
@@ -342,4 +347,4 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
instance.PushEntry(log_class, log_level, filename, line_num, function,
fmt::vformat(format, args));
}
-} // namespace Log
+} // namespace Common::Log
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index da1c2f185..9dd2589c3 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -11,7 +11,7 @@
#include "common/logging/filter.h"
#include "common/logging/log.h"
-namespace Log {
+namespace Common::Log {
class Filter;
@@ -94,8 +94,8 @@ public:
void Write(const Entry& entry) override;
private:
- Common::FS::IOFile file;
- std::size_t bytes_written;
+ FS::IOFile file;
+ std::size_t bytes_written = 0;
};
/**
@@ -135,4 +135,4 @@ const char* GetLevelName(Level log_level);
* never get the message
*/
void SetGlobalFilter(const Filter& filter);
-} // namespace Log \ No newline at end of file
+} // namespace Common::Log \ No newline at end of file
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index 2eccbcd8d..20a2dd106 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -7,7 +7,7 @@
#include "common/logging/filter.h"
#include "common/string_util.h"
-namespace Log {
+namespace Common::Log {
namespace {
template <typename It>
Level GetLevelByName(const It begin, const It end) {
@@ -103,4 +103,4 @@ bool Filter::IsDebug() const {
});
}
-} // namespace Log
+} // namespace Common::Log
diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h
index 773df6f2c..f5673a9f6 100644
--- a/src/common/logging/filter.h
+++ b/src/common/logging/filter.h
@@ -9,7 +9,7 @@
#include <string_view>
#include "common/logging/log.h"
-namespace Log {
+namespace Common::Log {
/**
* Implements a log message filter which allows different log classes to have different minimum
@@ -51,4 +51,4 @@ public:
private:
std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels;
};
-} // namespace Log
+} // namespace Common::Log
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 3d7b7dab7..1f0f8db52 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -7,7 +7,7 @@
#include <fmt/format.h>
#include "common/common_types.h"
-namespace Log {
+namespace Common::Log {
// trims up to and including the last of ../, ..\, src/, src\ in a string
constexpr const char* TrimSourcePath(std::string_view source) {
@@ -148,28 +148,34 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
fmt::make_format_args(args...));
}
-} // namespace Log
+} // namespace Common::Log
#ifdef _DEBUG
#define LOG_TRACE(log_class, ...) \
- ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, \
- ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
+ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Trace, \
+ Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
+ __VA_ARGS__)
#else
#define LOG_TRACE(log_class, fmt, ...) (void(0))
#endif
#define LOG_DEBUG(log_class, ...) \
- ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, \
- ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
+ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \
+ Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
+ __VA_ARGS__)
#define LOG_INFO(log_class, ...) \
- ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, \
- ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
+ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \
+ Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
+ __VA_ARGS__)
#define LOG_WARNING(log_class, ...) \
- ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, \
- ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
+ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \
+ Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
+ __VA_ARGS__)
#define LOG_ERROR(log_class, ...) \
- ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, \
- ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
+ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \
+ Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
+ __VA_ARGS__)
#define LOG_CRITICAL(log_class, ...) \
- ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, \
- ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
+ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \
+ Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
+ __VA_ARGS__)
diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp
index 6a0605c63..80ee2cca1 100644
--- a/src/common/logging/text_formatter.cpp
+++ b/src/common/logging/text_formatter.cpp
@@ -16,7 +16,7 @@
#include "common/logging/text_formatter.h"
#include "common/string_util.h"
-namespace Log {
+namespace Common::Log {
std::string FormatLogMessage(const Entry& entry) {
unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000);
@@ -108,4 +108,4 @@ void PrintColoredMessage(const Entry& entry) {
#undef ESC
#endif
}
-} // namespace Log
+} // namespace Common::Log
diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h
index b6d9e57c8..171e74cfe 100644
--- a/src/common/logging/text_formatter.h
+++ b/src/common/logging/text_formatter.h
@@ -7,7 +7,7 @@
#include <cstddef>
#include <string>
-namespace Log {
+namespace Common::Log {
struct Entry;
@@ -17,4 +17,4 @@ std::string FormatLogMessage(const Entry& entry);
void PrintMessage(const Entry& entry);
/// Prints the same message as `PrintMessage`, but colored according to the severity level.
void PrintColoredMessage(const Entry& entry);
-} // namespace Log
+} // namespace Common::Log
diff --git a/src/core/settings.cpp b/src/common/settings.cpp
index 2ae5196e0..702b6598d 100644
--- a/src/core/settings.cpp
+++ b/src/common/settings.cpp
@@ -1,4 +1,4 @@
-// Copyright 2014 Citra Emulator Project
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -7,10 +7,7 @@
#include "common/assert.h"
#include "common/file_util.h"
#include "common/logging/log.h"
-#include "core/core.h"
-#include "core/hle/service/hid/hid.h"
-#include "core/settings.h"
-#include "video_core/renderer_base.h"
+#include "common/settings.h"
namespace Settings {
@@ -32,14 +29,6 @@ std::string GetTimeZoneString() {
return timezones[time_zone_index];
}
-void Apply(Core::System& system) {
- if (system.IsPoweredOn()) {
- system.Renderer().RefreshBaseSettings();
- }
-
- Service::HID::ReloadInputDevices();
-}
-
void LogSettings() {
const auto log_setting = [](std::string_view name, const auto& value) {
LOG_INFO(Config, "{}: {}", name, value);
diff --git a/src/core/settings.h b/src/common/settings.h
index 6c03a6ea9..d39b4aa45 100644
--- a/src/core/settings.h
+++ b/src/common/settings.h
@@ -1,4 +1,4 @@
-// Copyright 2014 Citra Emulator Project
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -11,16 +11,13 @@
#include <optional>
#include <string>
#include <vector>
-#include "common/common_types.h"
-#include "input_common/settings.h"
-namespace Core {
-class System;
-}
+#include "common/common_types.h"
+#include "common/settings_input.h"
namespace Settings {
-enum class RendererBackend {
+enum class RendererBackend : u32 {
OpenGL = 0,
Vulkan = 1,
};
@@ -31,7 +28,7 @@ enum class GPUAccuracy : u32 {
Extreme = 2,
};
-enum class CPUAccuracy {
+enum class CPUAccuracy : u32 {
Accurate = 0,
Unsafe = 1,
DebugMode = 2,
@@ -223,6 +220,7 @@ struct Values {
bool quest_flag;
bool disable_macro_jit;
bool extended_logging;
+ bool use_debug_asserts;
bool use_auto_stub;
// Miscellaneous
@@ -255,7 +253,6 @@ float Volume();
std::string GetTimeZoneString();
-void Apply(Core::System& system);
void LogSettings();
// Restore the global state of all applicable settings in the Values struct
diff --git a/src/input_common/settings.cpp b/src/common/settings_input.cpp
index 557e7a9a0..bea2b837b 100644
--- a/src/input_common/settings.cpp
+++ b/src/common/settings_input.cpp
@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "input_common/settings.h"
+#include "common/settings_input.h"
namespace Settings {
namespace NativeButton {
diff --git a/src/input_common/settings.h b/src/common/settings_input.h
index a59f5d461..609600582 100644
--- a/src/input_common/settings.h
+++ b/src/common/settings_input.h
@@ -6,6 +6,7 @@
#include <array>
#include <string>
+
#include "common/common_types.h"
namespace Settings {
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 167ee13f3..04cf3f5b9 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -273,6 +273,7 @@ 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
@@ -376,6 +377,8 @@ add_library(core STATIC
hle/service/glue/arp.h
hle/service/glue/bgtc.cpp
hle/service/glue/bgtc.h
+ hle/service/glue/ectx.cpp
+ hle/service/glue/ectx.h
hle/service/glue/errors.h
hle/service/glue/glue.cpp
hle/service/glue/glue.h
@@ -621,8 +624,6 @@ add_library(core STATIC
perf_stats.h
reporter.cpp
reporter.h
- settings.cpp
- settings.h
telemetry_session.cpp
telemetry_session.h
tools/freezer.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 08d889135..7aeb2a658 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -10,6 +10,7 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/page_table.h"
+#include "common/settings.h"
#include "core/arm/cpu_interrupt_handler.h"
#include "core/arm/dynarmic/arm_dynarmic_32.h"
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
@@ -18,7 +19,6 @@
#include "core/core_timing.h"
#include "core/hle/kernel/svc.h"
#include "core/memory.h"
-#include "core/settings.h"
namespace Core {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index e12e50658..040529f4d 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -9,6 +9,7 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/page_table.h"
+#include "common/settings.h"
#include "core/arm/cpu_interrupt_handler.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/arm/dynarmic/arm_exclusive_monitor.h"
@@ -19,7 +20,6 @@
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/svc.h"
#include "core/memory.h"
-#include "core/settings.h"
namespace Core {
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 56b47e671..d459d6c34 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -9,6 +9,7 @@
#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core.h"
@@ -36,6 +37,7 @@
#include "core/hle/service/apm/controller.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/glue/manager.h"
+#include "core/hle/service/hid/hid.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/time/time_manager.h"
@@ -45,7 +47,6 @@
#include "core/network/network.h"
#include "core/perf_stats.h"
#include "core/reporter.h"
-#include "core/settings.h"
#include "core/telemetry_session.h"
#include "core/tools/freezer.h"
#include "video_core/renderer_base.h"
@@ -774,4 +775,12 @@ void System::ExecuteProgram(std::size_t program_index) {
}
}
+void System::ApplySettings() {
+ if (IsPoweredOn()) {
+ Renderer().RefreshBaseSettings();
+ }
+
+ Service::HID::ReloadInputDevices();
+}
+
} // namespace Core
diff --git a/src/core/core.h b/src/core/core.h
index 3a8e040c1..f1068d23f 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -388,6 +388,9 @@ public:
*/
void ExecuteProgram(std::size_t program_index);
+ /// Applies any changes to settings to this core instance.
+ void ApplySettings();
+
private:
System();
diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp
index cb7506241..85a666de9 100644
--- a/src/core/crypto/aes_util.cpp
+++ b/src/core/crypto/aes_util.cpp
@@ -119,9 +119,9 @@ void AESCipher<Key, KeySize>::XTSTranscode(const u8* src, std::size_t size, u8*
}
template <typename Key, std::size_t KeySize>
-void AESCipher<Key, KeySize>::SetIVImpl(const u8* data, std::size_t size) {
- ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, data, size) ||
- mbedtls_cipher_set_iv(&ctx->decryption_context, data, size)) == 0,
+void AESCipher<Key, KeySize>::SetIV(std::span<const u8> data) {
+ ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, data.data(), data.size()) ||
+ mbedtls_cipher_set_iv(&ctx->decryption_context, data.data(), data.size())) == 0,
"Failed to set IV on mbedtls ciphers.");
}
diff --git a/src/core/crypto/aes_util.h b/src/core/crypto/aes_util.h
index e2a304186..230451b8f 100644
--- a/src/core/crypto/aes_util.h
+++ b/src/core/crypto/aes_util.h
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
+#include <span>
#include <type_traits>
#include "common/common_types.h"
#include "core/file_sys/vfs.h"
@@ -33,10 +34,7 @@ public:
AESCipher(Key key, Mode mode);
~AESCipher();
- template <typename ContiguousContainer>
- void SetIV(const ContiguousContainer& container) {
- SetIVImpl(std::data(container), std::size(container));
- }
+ void SetIV(std::span<const u8> data);
template <typename Source, typename Dest>
void Transcode(const Source* src, std::size_t size, Dest* dest, Op op) const {
@@ -60,8 +58,6 @@ public:
std::size_t sector_size, Op op);
private:
- void SetIVImpl(const u8* data, std::size_t size);
-
std::unique_ptr<CipherContext> ctx;
};
} // namespace Core::Crypto
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index ad116dcc0..070ed439e 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -22,6 +22,7 @@
#include "common/file_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/crypto/aes_util.h"
#include "core/crypto/key_manager.h"
@@ -32,7 +33,6 @@
#include "core/file_sys/registered_cache.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
-#include "core/settings.h"
namespace Core::Crypto {
namespace {
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 7c3284df8..cc9b4b637 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -10,6 +10,7 @@
#include "common/file_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/file_sys/common_funcs.h"
@@ -25,7 +26,6 @@
#include "core/loader/loader.h"
#include "core/loader/nso.h"
#include "core/memory/cheat_engine.h"
-#include "core/settings.h"
namespace FileSys {
namespace {
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index 9cf49bf44..83b83a044 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -58,7 +58,8 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
result.LoadManual(
true /*is_64_bit*/, FileSys::ProgramAddressSpaceType::Is39Bit /*address_space*/,
0x2c /*main_thread_prio*/, 0 /*main_thread_core*/, 0x00100000 /*main_thread_stack_size*/,
- {}, 0xFFFFFFFFFFFFFFFF /*filesystem_permissions*/, {} /*capabilities*/);
+ 0 /*title_id*/, 0xFFFFFFFFFFFFFFFF /*filesystem_permissions*/,
+ 0x1FE00000 /*system_resource_size*/, {} /*capabilities*/);
return result;
}
@@ -66,7 +67,7 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
void ProgramMetadata::LoadManual(bool is_64_bit, ProgramAddressSpaceType address_space,
s32 main_thread_prio, u32 main_thread_core,
u32 main_thread_stack_size, u64 title_id,
- u64 filesystem_permissions,
+ u64 filesystem_permissions, u32 system_resource_size,
KernelCapabilityDescriptors capabilities) {
npdm_header.has_64_bit_instructions.Assign(is_64_bit);
npdm_header.address_space_type.Assign(address_space);
@@ -75,6 +76,7 @@ void ProgramMetadata::LoadManual(bool is_64_bit, ProgramAddressSpaceType address
npdm_header.main_stack_size = main_thread_stack_size;
aci_header.title_id = title_id;
aci_file_access.permissions = filesystem_permissions;
+ npdm_header.system_resource_size = system_resource_size;
aci_kernel_capabilities = std ::move(capabilities);
}
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index 455532567..1eee916be 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -44,6 +44,12 @@ public:
ProgramMetadata();
~ProgramMetadata();
+ ProgramMetadata(const ProgramMetadata&) = default;
+ ProgramMetadata& operator=(const ProgramMetadata&) = default;
+
+ ProgramMetadata(ProgramMetadata&&) = default;
+ ProgramMetadata& operator=(ProgramMetadata&&) = default;
+
/// Gets a default ProgramMetadata configuration, should only be used for homebrew formats where
/// we do not have an NPDM file
static ProgramMetadata GetDefault();
@@ -53,7 +59,8 @@ public:
/// Load from parameters instead of NPDM file, used for KIP
void LoadManual(bool is_64_bit, ProgramAddressSpaceType address_space, s32 main_thread_prio,
u32 main_thread_core, u32 main_thread_stack_size, u64 title_id,
- u64 filesystem_permissions, KernelCapabilityDescriptors capabilities);
+ u64 filesystem_permissions, u32 system_resource_size,
+ KernelCapabilityDescriptors capabilities);
bool Is64BitProgram() const;
ProgramAddressSpaceType GetAddressSpaceType() const;
diff --git a/src/core/frontend/applets/profile_select.cpp b/src/core/frontend/applets/profile_select.cpp
index 4df3574d2..8d960d1ca 100644
--- a/src/core/frontend/applets/profile_select.cpp
+++ b/src/core/frontend/applets/profile_select.cpp
@@ -2,9 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/settings.h"
#include "core/frontend/applets/profile_select.h"
#include "core/hle/service/acc/profile_manager.h"
-#include "core/settings.h"
namespace Core::Frontend {
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp
index 856ed33da..12c76c9ee 100644
--- a/src/core/frontend/applets/software_keyboard.cpp
+++ b/src/core/frontend/applets/software_keyboard.cpp
@@ -1,29 +1,149 @@
-// Copyright 2018 yuzu emulator team
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "common/logging/backend.h"
+#include <thread>
+
+#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/frontend/applets/software_keyboard.h"
namespace Core::Frontend {
+
SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default;
-void DefaultSoftwareKeyboardApplet::RequestText(
- std::function<void(std::optional<std::u16string>)> out,
- SoftwareKeyboardParameters parameters) const {
- if (parameters.initial_text.empty())
- out(u"yuzu");
+DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default;
+
+void DefaultSoftwareKeyboardApplet::InitializeKeyboard(
+ bool is_inline, KeyboardInitializeParameters initialize_parameters,
+ std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_,
+ std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ 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);
+}
+
+void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const {
+ LOG_WARNING(Service_AM,
+ "(STUBBED) called, backend requested to show the normal software keyboard.");
+
+ SubmitNormalText(u"yuzu");
+}
+
+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();
+}
- out(parameters.initial_text);
+void DefaultSoftwareKeyboardApplet::HideInlineKeyboard() const {
+ LOG_WARNING(Service_AM,
+ "(STUBBED) called, backend requested to hide the inline software keyboard.");
}
-void DefaultSoftwareKeyboardApplet::SendTextCheckDialog(
- std::u16string error_message, std::function<void()> finished_check) const {
+void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_parameters) const {
LOG_WARNING(Service_AM,
- "(STUBBED) called - Default fallback software keyboard does not support text "
- "check! (error_message={})",
- Common::UTF16ToUTF8(error_message));
- finished_check();
+ "(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<s32>(index) + 1);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(250));
+ }
+
+ submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, std::u16string(text),
+ static_cast<s32>(text.size()));
+}
+
} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h
index f9b202664..506eb35bb 100644
--- a/src/core/frontend/applets/software_keyboard.h
+++ b/src/core/frontend/applets/software_keyboard.h
@@ -1,54 +1,116 @@
-// Copyright 2018 yuzu emulator team
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <functional>
-#include <optional>
-#include <string>
-#include "common/bit_field.h"
+#include <thread>
+
#include "common/common_types.h"
+#include "core/hle/service/am/applets/software_keyboard_types.h"
+
namespace Core::Frontend {
-struct SoftwareKeyboardParameters {
- std::u16string submit_text;
+
+struct KeyboardInitializeParameters {
+ std::u16string ok_text;
std::u16string header_text;
std::u16string sub_text;
std::u16string guide_text;
std::u16string initial_text;
- std::size_t max_length;
- bool password;
- bool cursor_at_beginning;
-
- union {
- u8 value;
-
- 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;
- };
+ 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;
+};
+
+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;
+};
+
+struct InlineTextParameters {
+ std::u16string input_text;
+ s32 cursor_position;
};
class SoftwareKeyboardApplet {
public:
virtual ~SoftwareKeyboardApplet();
- virtual void RequestText(std::function<void(std::optional<std::u16string>)> out,
- SoftwareKeyboardParameters parameters) const = 0;
- virtual void SendTextCheckDialog(std::u16string error_message,
- std::function<void()> finished_check) const = 0;
+ virtual void InitializeKeyboard(
+ bool is_inline, KeyboardInitializeParameters initialize_parameters,
+ std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
+ submit_normal_callback_,
+ std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ 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;
};
class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
public:
- void RequestText(std::function<void(std::optional<std::u16string>)> out,
- SoftwareKeyboardParameters parameters) const override;
- void SendTextCheckDialog(std::u16string error_message,
- std::function<void()> finished_check) const override;
+ ~DefaultSoftwareKeyboardApplet() override;
+
+ void InitializeKeyboard(
+ bool is_inline, KeyboardInitializeParameters initialize_parameters,
+ std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
+ submit_normal_callback_,
+ std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ 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<void(Service::AM::Applets::SwkbdResult, std::u16string)>
+ submit_normal_callback;
+ mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ submit_inline_callback;
};
} // namespace Core::Frontend
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp
index ee7a58b1c..cff49899a 100644
--- a/src/core/frontend/emu_window.cpp
+++ b/src/core/frontend/emu_window.cpp
@@ -4,9 +4,9 @@
#include <cmath>
#include <mutex>
+#include "common/settings.h"
#include "core/frontend/emu_window.h"
#include "core/frontend/input.h"
-#include "core/settings.h"
namespace Core::Frontend {
@@ -60,23 +60,23 @@ EmuWindow::~EmuWindow() {
* @param framebuffer_y Framebuffer y-coordinate to check
* @return True if the coordinates are within the touchpad, otherwise false
*/
-static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x,
- unsigned framebuffer_y) {
+static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, u32 framebuffer_x,
+ u32 framebuffer_y) {
return (framebuffer_y >= layout.screen.top && framebuffer_y < layout.screen.bottom &&
framebuffer_x >= layout.screen.left && framebuffer_x < layout.screen.right);
}
-std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const {
+std::pair<u32, u32> EmuWindow::ClipToTouchScreen(u32 new_x, u32 new_y) const {
new_x = std::max(new_x, framebuffer_layout.screen.left);
new_x = std::min(new_x, framebuffer_layout.screen.right - 1);
new_y = std::max(new_y, framebuffer_layout.screen.top);
new_y = std::min(new_y, framebuffer_layout.screen.bottom - 1);
- return std::make_tuple(new_x, new_y);
+ return std::make_pair(new_x, new_y);
}
-void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id) {
+void EmuWindow::TouchPressed(u32 framebuffer_x, u32 framebuffer_y, size_t id) {
if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) {
return;
}
@@ -95,7 +95,7 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y, std
touch_state->status[id] = std::make_tuple(x, y, true);
}
-void EmuWindow::TouchReleased(std::size_t id) {
+void EmuWindow::TouchReleased(size_t id) {
if (id >= touch_state->status.size()) {
return;
}
@@ -103,20 +103,23 @@ void EmuWindow::TouchReleased(std::size_t id) {
touch_state->status[id] = std::make_tuple(0.0f, 0.0f, false);
}
-void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id) {
+void EmuWindow::TouchMoved(u32 framebuffer_x, u32 framebuffer_y, size_t id) {
if (id >= touch_state->status.size()) {
return;
}
- if (!std::get<2>(touch_state->status[id]))
+
+ if (!std::get<2>(touch_state->status[id])) {
return;
+ }
- if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y))
+ if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) {
std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y);
+ }
TouchPressed(framebuffer_x, framebuffer_y, id);
}
-void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) {
+void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height) {
NotifyFramebufferLayoutChanged(Layout::DefaultFrameLayout(width, height));
}
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index 2436c6580..076148698 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -82,7 +82,7 @@ public:
bool fullscreen = false;
int res_width = 0;
int res_height = 0;
- std::pair<unsigned, unsigned> min_client_area_size;
+ std::pair<u32, u32> min_client_area_size;
};
/// Data describing host window system information
@@ -119,13 +119,13 @@ public:
* @param framebuffer_y Framebuffer y-coordinate that was pressed
* @param id Touch event ID
*/
- void TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id);
+ void TouchPressed(u32 framebuffer_x, u32 framebuffer_y, size_t id);
/**
* Signal that a touch released event has occurred (e.g. mouse click released)
* @param id Touch event ID
*/
- void TouchReleased(std::size_t id);
+ void TouchReleased(size_t id);
/**
* Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window)
@@ -133,7 +133,7 @@ public:
* @param framebuffer_y Framebuffer y-coordinate
* @param id Touch event ID
*/
- void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id);
+ void TouchMoved(u32 framebuffer_x, u32 framebuffer_y, size_t id);
/**
* Returns currently active configuration.
@@ -173,7 +173,7 @@ public:
* Convenience method to update the current frame layout
* Read from the current settings to determine which layout to use.
*/
- void UpdateCurrentFramebufferLayout(unsigned width, unsigned height);
+ void UpdateCurrentFramebufferLayout(u32 width, u32 height);
protected:
explicit EmuWindow();
@@ -208,7 +208,7 @@ protected:
* Update internal client area size with the given parameter.
* @note EmuWindow implementations will usually use this in window resize event handlers.
*/
- void NotifyClientAreaSizeChanged(const std::pair<unsigned, unsigned>& size) {
+ void NotifyClientAreaSizeChanged(std::pair<u32, u32> size) {
client_area_width = size.first;
client_area_height = size.second;
}
@@ -221,14 +221,19 @@ private:
* For the request to be honored, EmuWindow implementations will usually reimplement this
* function.
*/
- virtual void OnMinimalClientAreaChangeRequest(std::pair<unsigned, unsigned>) {
+ virtual void OnMinimalClientAreaChangeRequest(std::pair<u32, u32>) {
// By default, ignore this request and do nothing.
}
+ /**
+ * Clip the provided coordinates to be inside the touchscreen area.
+ */
+ std::pair<u32, u32> ClipToTouchScreen(u32 new_x, u32 new_y) const;
+
Layout::FramebufferLayout framebuffer_layout; ///< Current framebuffer layout
- unsigned client_area_width; ///< Current client width, should be set by window impl.
- unsigned client_area_height; ///< Current client height, should be set by window impl.
+ u32 client_area_width; ///< Current client width, should be set by window impl.
+ u32 client_area_height; ///< Current client height, should be set by window impl.
WindowConfig config; ///< Internal configuration (changes pending for being applied in
/// ProcessConfigurationChanges)
@@ -236,11 +241,6 @@ private:
class TouchState;
std::shared_ptr<TouchState> touch_state;
-
- /**
- * Clip the provided coordinates to be inside the touchscreen area.
- */
- std::tuple<unsigned, unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y) const;
};
} // namespace Core::Frontend
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp
index b9a270a55..0832463d6 100644
--- a/src/core/frontend/framebuffer_layout.cpp
+++ b/src/core/frontend/framebuffer_layout.cpp
@@ -5,8 +5,8 @@
#include <cmath>
#include "common/assert.h"
+#include "common/settings.h"
#include "core/frontend/framebuffer_layout.h"
-#include "core/settings.h"
namespace Layout {
diff --git a/src/core/frontend/input_interpreter.cpp b/src/core/frontend/input_interpreter.cpp
index ec5fe660e..9f6a90e8f 100644
--- a/src/core/frontend/input_interpreter.cpp
+++ b/src/core/frontend/input_interpreter.cpp
@@ -12,7 +12,9 @@ InputInterpreter::InputInterpreter(Core::System& system)
: npad{system.ServiceManager()
.GetService<Service::HID::Hid>("hid")
->GetAppletResource()
- ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {}
+ ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {
+ ResetButtonStates();
+}
InputInterpreter::~InputInterpreter() = default;
@@ -25,6 +27,17 @@ 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<u8>(button))) != 0;
}
diff --git a/src/core/frontend/input_interpreter.h b/src/core/frontend/input_interpreter.h
index 73fc47ffb..9495e3daf 100644
--- a/src/core/frontend/input_interpreter.h
+++ b/src/core/frontend/input_interpreter.h
@@ -66,6 +66,9 @@ 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 161d9f782..2b363b1d9 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -75,10 +75,14 @@ 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) {
- copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
+ const u32 copy_handle{rp.Pop<Handle>()};
+ copy_handles.push_back(copy_handle);
+ copy_objects.push_back(handle_table.GetGeneric(copy_handle));
}
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) {
- move_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
+ const u32 move_handle{rp.Pop<Handle>()};
+ move_handles.push_back(move_handle);
+ move_objects.push_back(handle_table.GetGeneric(move_handle));
}
} 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 9a769781b..6fba42615 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -210,6 +210,14 @@ 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 <typename T>
std::shared_ptr<T> GetCopyObject(std::size_t index) {
return DynamicObjectCast<T>(copy_objects.at(index));
@@ -285,6 +293,8 @@ private:
std::shared_ptr<Kernel::ServerSession> server_session;
std::shared_ptr<KThread> thread;
// TODO(yuriks): Check common usage of this and optimize size accordingly
+ boost::container::small_vector<Handle, 8> move_handles;
+ boost::container::small_vector<Handle, 8> copy_handles;
boost::container::small_vector<std::shared_ptr<Object>, 8> move_objects;
boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects;
boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects;
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index d7a4a38e6..d05b34ea3 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -2,21 +2,16 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
#include "common/assert.h"
-#include "core/core.h"
#include "core/core_timing.h"
-#include "core/core_timing_util.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
-KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system)
- : Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {}
+KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_)
+ : Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {}
KResourceLimit::~KResourceLimit() = default;
s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
@@ -83,7 +78,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
}
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
- return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout);
+ return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout);
}
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
@@ -114,7 +109,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
}
if (current_hints[index] + value <= limit_values[index] &&
- (timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) {
+ (timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) {
waiter_count++;
cond_var.Wait(&lock, timeout);
waiter_count--;
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 58ae456f1..4542317d0 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -2,9 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
#pragma once
#include <array>
@@ -15,8 +12,8 @@
union ResultCode;
-namespace Core {
-class System;
+namespace Core::Timing {
+class CoreTiming;
}
namespace Kernel {
@@ -37,7 +34,7 @@ constexpr bool IsValidResourceType(LimitableResource type) {
class KResourceLimit final : public Object {
public:
- explicit KResourceLimit(KernelCore& kernel, Core::System& system);
+ explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_);
~KResourceLimit();
s64 GetLimitValue(LimitableResource which) const;
@@ -75,7 +72,6 @@ private:
mutable KLightLock lock;
s32 waiter_count{};
KLightConditionVariable cond_var;
- KernelCore& kernel;
- Core::System& system;
+ const Core::Timing::CoreTiming& core_timing;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index f7d3f218a..5c4f45ab4 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -72,7 +72,7 @@ struct KernelCore::Impl {
KMemoryLayout memory_layout;
DeriveInitialMemoryLayout(memory_layout);
InitializeMemoryLayout(memory_layout);
- InitializeSystemResourceLimit(kernel, system, memory_layout);
+ InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout);
InitializeSlabHeaps();
InitializeSchedulers();
InitializeSuspendThreads();
@@ -142,9 +142,10 @@ struct KernelCore::Impl {
}
// Creates the default system resource limit
- void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system,
+ void InitializeSystemResourceLimit(KernelCore& kernel,
+ const Core::Timing::CoreTiming& core_timing,
const KMemoryLayout& memory_layout) {
- system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
+ system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing);
const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes();
// If setting the default system values fails, then something seriously wrong has occurred.
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index dd01f3924..e35deb8e2 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -10,6 +10,7 @@
#include "common/alignment.h"
#include "common/assert.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/device_memory.h"
#include "core/file_sys/program_metadata.h"
@@ -26,7 +27,6 @@
#include "core/hle/kernel/svc_results.h"
#include "core/hle/lock.h"
#include "core/memory.h"
-#include "core/settings.h"
namespace Kernel {
namespace {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index fcffc746d..bebb86154 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -2156,7 +2156,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
LOG_DEBUG(Kernel_SVC, "called");
auto& kernel = system.Kernel();
- auto resource_limit = std::make_shared<KResourceLimit>(kernel, system);
+ auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming());
auto* const current_process = kernel.CurrentProcess();
ASSERT(current_process != nullptr);
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 52535ecc0..5450dcf0f 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -702,16 +702,12 @@ void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestCon
}
void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(InitializeApplicationInfoBase());
}
void Module::Interface::InitializeApplicationInfoRestricted(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
LOG_WARNING(Service_ACC, "(Partial implementation) called");
// TODO(ogniK): We require checking if the user actually owns the title and what not. As of
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 50b2c58e2..de83d82a4 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -8,8 +8,8 @@
#include <fmt/format.h>
#include "common/file_util.h"
+#include "common/settings.h"
#include "core/hle/service/acc/profile_manager.h"
-#include "core/settings.h"
namespace Service::Account {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 4374487a3..58c7f2930 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -7,6 +7,7 @@
#include <cinttypes>
#include <cstring>
#include "audio_core/audio_renderer.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
@@ -41,7 +42,6 @@
#include "core/hle/service/set/set.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/vi/vi.h"
-#include "core/settings.h"
namespace Service::AM {
@@ -619,16 +619,20 @@ std::size_t AppletMessageQueue::GetMessageCount() const {
return messages.size();
}
+void AppletMessageQueue::RequestExit() {
+ PushMessage(AppletMessage::ExitRequested);
+}
+
+void AppletMessageQueue::FocusStateChanged() {
+ PushMessage(AppletMessage::FocusStateChanged);
+}
+
void AppletMessageQueue::OperationModeChanged() {
PushMessage(AppletMessage::OperationModeChanged);
PushMessage(AppletMessage::PerformanceModeChanged);
on_operation_mode_changed->GetWritableEvent()->Signal();
}
-void AppletMessageQueue::RequestExit() {
- PushMessage(AppletMessage::ExitRequested);
-}
-
ICommonStateGetter::ICommonStateGetter(Core::System& system_,
std::shared_ptr<AppletMessageQueue> msg_queue_)
: ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)} {
@@ -683,7 +687,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
{501, nullptr, "SuppressDisablingSleepTemporarily"},
{502, nullptr, "IsSleepEnabled"},
{503, nullptr, "IsDisablingSleepSuppressed"},
- {900, nullptr, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
+ {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
};
// clang-format on
@@ -813,6 +817,14 @@ void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) {
apm_sys->SetCpuBoostMode(ctx);
}
+void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
+ Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
IStorageImpl::~IStorageImpl() = default;
class StorageDataImpl final : public IStorageImpl {
@@ -971,7 +983,7 @@ private:
auto storage = applet->GetBroker().PopNormalDataToGame();
if (storage == nullptr) {
- LOG_ERROR(Service_AM,
+ LOG_DEBUG(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 +1014,7 @@ private:
auto storage = applet->GetBroker().PopInteractiveDataToGame();
if (storage == nullptr) {
- LOG_ERROR(Service_AM,
+ LOG_DEBUG(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 +1137,7 @@ ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
{2, nullptr, "AreAnyLibraryAppletsLeft"},
{10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
{11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
- {12, nullptr, "CreateHandleStorage"},
+ {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
};
RegisterHandlers(functions);
}
@@ -1134,14 +1146,15 @@ ILibraryAppletCreator::~ILibraryAppletCreator() = default;
void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
+
const auto applet_id = rp.PopRaw<Applets::AppletId>();
- const auto applet_mode = rp.PopRaw<u32>();
+ const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
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);
+ const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
if (applet == nullptr) {
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
@@ -1159,9 +1172,18 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const u64 size{rp.Pop<u64>()};
+
+ const s64 size{rp.Pop<s64>()};
+
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<u8> buffer(size);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -1170,18 +1192,65 @@ 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<Parameters>()};
+ 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;
+ }
+
+ auto transfer_mem =
+ system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(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<u8> memory{mem_begin, mem_end};
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IStorage>(system, std::move(memory));
+}
+
+void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- rp.SetCurrentOffset(3);
- const auto handle{rp.Pop<Kernel::Handle>()};
+ const s64 size{rp.Pop<s64>()};
+ 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<Kernel::TransferMemory>(handle);
if (transfer_mem == nullptr) {
- LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle);
+ LOG_ERROR(Service_AM, "transfer_mem is a nullptr 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 f6a453ab7..5d302e155 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -61,8 +61,9 @@ public:
void PushMessage(AppletMessage msg);
AppletMessage PopMessage();
std::size_t GetMessageCount() const;
- void OperationModeChanged();
void RequestExit();
+ void FocusStateChanged();
+ void OperationModeChanged();
private:
std::queue<AppletMessage> messages;
@@ -195,6 +196,7 @@ private:
void EndVrModeEx(Kernel::HLERequestContext& ctx);
void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
+ void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(Kernel::HLERequestContext& ctx);
std::shared_ptr<AppletMessageQueue> msg_queue;
bool vr_mode_state{};
@@ -254,6 +256,7 @@ 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<IApplicationFunctions> {
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index e2f3b7563..a56df6a7e 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -17,6 +17,8 @@
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/service/am/am.h"
+#include "core/hle/service/am/applet_ae.h"
+#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applets/controller.h"
#include "core/hle/service/am/applets/error.h"
@@ -24,17 +26,20 @@
#include "core/hle/service/am/applets/profile_select.h"
#include "core/hle/service/am/applets/software_keyboard.h"
#include "core/hle/service/am/applets/web_browser.h"
+#include "core/hle/service/sm/sm.h"
namespace Service::AM::Applets {
-AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
+AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_)
+ : system{system_}, applet_mode{applet_mode_} {
state_changed_event =
- Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:StateChangedEvent");
+ Kernel::KEvent::Create(system.Kernel(), "ILibraryAppletAccessor:StateChangedEvent");
state_changed_event->Initialize();
- pop_out_data_event = Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
+ pop_out_data_event =
+ Kernel::KEvent::Create(system.Kernel(), "ILibraryAppletAccessor:PopDataOutEvent");
pop_out_data_event->Initialize();
- pop_interactive_out_data_event =
- Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
+ pop_interactive_out_data_event = Kernel::KEvent::Create(
+ system.Kernel(), "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
pop_interactive_out_data_event->Initialize();
}
@@ -114,6 +119,27 @@ void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&&
void AppletDataBroker::SignalStateChanged() const {
state_changed_event->GetWritableEvent()->Signal();
+
+ switch (applet_mode) {
+ case LibraryAppletMode::AllForeground:
+ case LibraryAppletMode::AllForegroundInitiallyHidden: {
+ auto applet_oe = system.ServiceManager().GetService<AppletOE>("appletOE");
+ auto applet_ae = system.ServiceManager().GetService<AppletAE>("appletAE");
+
+ if (applet_oe) {
+ applet_oe->GetMessageQueue()->FocusStateChanged();
+ break;
+ }
+
+ if (applet_ae) {
+ applet_ae->GetMessageQueue()->FocusStateChanged();
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
@@ -128,7 +154,8 @@ std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetStateChangedEvent()
return state_changed_event->GetReadableEvent();
}
-Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {}
+Applet::Applet(Core::System& system_, LibraryAppletMode applet_mode_)
+ : broker{system_, applet_mode_}, applet_mode{applet_mode_} {}
Applet::~Applet() = default;
@@ -241,31 +268,31 @@ void AppletManager::ClearAll() {
frontend = {};
}
-std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
+std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const {
switch (id) {
case AppletId::Auth:
- return std::make_shared<Auth>(system, *frontend.parental_controls);
+ return std::make_shared<Auth>(system, mode, *frontend.parental_controls);
case AppletId::Controller:
- return std::make_shared<Controller>(system, *frontend.controller);
+ return std::make_shared<Controller>(system, mode, *frontend.controller);
case AppletId::Error:
- return std::make_shared<Error>(system, *frontend.error);
+ return std::make_shared<Error>(system, mode, *frontend.error);
case AppletId::ProfileSelect:
- return std::make_shared<ProfileSelect>(system, *frontend.profile_select);
+ return std::make_shared<ProfileSelect>(system, mode, *frontend.profile_select);
case AppletId::SoftwareKeyboard:
- return std::make_shared<SoftwareKeyboard>(system, *frontend.software_keyboard);
+ return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard);
case AppletId::Web:
case AppletId::Shop:
case AppletId::OfflineWeb:
case AppletId::LoginShare:
case AppletId::WebAuth:
- return std::make_shared<WebBrowser>(system, *frontend.web_browser);
+ return std::make_shared<WebBrowser>(system, mode, *frontend.web_browser);
case AppletId::PhotoViewer:
- return std::make_shared<PhotoViewer>(system, *frontend.photo_viewer);
+ return std::make_shared<PhotoViewer>(system, mode, *frontend.photo_viewer);
default:
UNIMPLEMENTED_MSG(
"No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
static_cast<u8>(id));
- return std::make_shared<StubApplet>(system, id);
+ return std::make_shared<StubApplet>(system, id, mode);
}
}
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index b9a006317..4215d2232 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -62,9 +62,17 @@ 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_);
+ explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_);
~AppletDataBroker();
struct RawChannelData {
@@ -94,6 +102,9 @@ public:
std::shared_ptr<Kernel::KReadableEvent> GetStateChangedEvent() const;
private:
+ Core::System& system;
+ LibraryAppletMode applet_mode;
+
// Queues are named from applet's perspective
// PopNormalDataToApplet and PushNormalDataFromGame
@@ -119,7 +130,7 @@ private:
class Applet {
public:
- explicit Applet(Kernel::KernelCore& kernel_);
+ explicit Applet(Core::System& system_, LibraryAppletMode applet_mode_);
virtual ~Applet();
virtual void Initialize();
@@ -129,10 +140,6 @@ public:
virtual void ExecuteInteractive() = 0;
virtual void Execute() = 0;
- bool IsInitialized() const {
- return initialized;
- }
-
AppletDataBroker& GetBroker() {
return broker;
}
@@ -141,6 +148,14 @@ public:
return broker;
}
+ LibraryAppletMode GetLibraryAppletMode() const {
+ return applet_mode;
+ }
+
+ bool IsInitialized() const {
+ return initialized;
+ }
+
protected:
struct CommonArguments {
u32_le arguments_version;
@@ -154,6 +169,7 @@ protected:
CommonArguments common_args{};
AppletDataBroker broker;
+ LibraryAppletMode applet_mode;
bool initialized = false;
};
@@ -200,7 +216,7 @@ public:
void SetDefaultAppletsIfMissing();
void ClearAll();
- std::shared_ptr<Applet> GetApplet(AppletId id) const;
+ std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) 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 c2bfe698f..218c8d1e4 100644
--- a/src/core/hle/service/am/applets/controller.cpp
+++ b/src/core/hle/service/am/applets/controller.cpp
@@ -45,8 +45,9 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
};
}
-Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::ControllerApplet& frontend_)
+ : Applet{system_, applet_mode_}, 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 d4c9da7b1..2d4dae0bd 100644
--- a/src/core/hle/service/am/applets/controller.h
+++ b/src/core/hle/service/am/applets/controller.h
@@ -106,7 +106,8 @@ static_assert(sizeof(ControllerSupportResultInfo) == 0xC,
class Controller final : public Applet {
public:
- explicit Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_);
+ explicit Controller(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::ControllerApplet& frontend_);
~Controller() override;
void Initialize() override;
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
index 0c8b632e8..23e30aa45 100644
--- a/src/core/hle/service/am/applets/error.cpp
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -86,8 +86,9 @@ ResultCode Decode64BitError(u64 error) {
} // Anonymous namespace
-Error::Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+Error::Error(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::ErrorApplet& frontend_)
+ : Applet{system_, applet_mode_}, 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 a105cdb0c..e606d12ce 100644
--- a/src/core/hle/service/am/applets/error.h
+++ b/src/core/hle/service/am/applets/error.h
@@ -25,7 +25,8 @@ enum class ErrorAppletMode : u8 {
class Error final : public Applet {
public:
- explicit Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_);
+ explicit Error(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::ErrorApplet& frontend_);
~Error() override;
void Initialize() override;
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index 4d1df5cbe..b26abad36 100644
--- a/src/core/hle/service/am/applets/general_backend.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -37,8 +37,9 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix)
}
}
-Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_,
+ Core::Frontend::ParentalControlsApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
Auth::~Auth() = default;
@@ -152,8 +153,9 @@ void Auth::AuthFinished(bool is_successful) {
broker.SignalStateChanged();
}
-PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::PhotoViewerApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
PhotoViewer::~PhotoViewer() = default;
@@ -202,8 +204,8 @@ void PhotoViewer::ViewFinished() {
broker.SignalStateChanged();
}
-StubApplet::StubApplet(Core::System& system_, AppletId id_)
- : Applet{system_.Kernel()}, id{id_}, system{system_} {}
+StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_)
+ : Applet{system_, applet_mode_}, 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 ba76ae3d3..7496ded88 100644
--- a/src/core/hle/service/am/applets/general_backend.h
+++ b/src/core/hle/service/am/applets/general_backend.h
@@ -20,7 +20,8 @@ enum class AuthAppletType : u32 {
class Auth final : public Applet {
public:
- explicit Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_);
+ explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_,
+ Core::Frontend::ParentalControlsApplet& frontend_);
~Auth() override;
void Initialize() override;
@@ -50,7 +51,8 @@ enum class PhotoViewerAppletMode : u8 {
class PhotoViewer final : public Applet {
public:
- explicit PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_);
+ explicit PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::PhotoViewerApplet& frontend_);
~PhotoViewer() override;
void Initialize() override;
@@ -70,7 +72,7 @@ private:
class StubApplet final : public Applet {
public:
- explicit StubApplet(Core::System& system_, AppletId id_);
+ explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_);
~StubApplet() override;
void Initialize() override;
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index 77fba16c7..c91a9776a 100644
--- 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_,
+ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::ProfileSelectApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+ : Applet{system_, applet_mode_}, 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 648d33a24..f0dd6c1f3 100644
--- 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_,
+ explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::ProfileSelectApplet& frontend_);
~ProfileSelect() override;
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 79b209c6b..73a06def1 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -1,93 +1,80 @@
-// Copyright 2018 yuzu emulator team
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cstring>
-#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 {
-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;
+
+// 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<u8>& reply, SwkbdState state, SwkbdReplyType reply_type) {
+ std::memcpy(reply.data(), &state, sizeof(SwkbdState));
+ std::memcpy(reply.data() + sizeof(SwkbdState), &reply_type, sizeof(SwkbdReplyType));
+}
+
} // Anonymous namespace
-static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
- KeyboardConfig config, std::u16string initial_text) {
- Core::Frontend::SoftwareKeyboardParameters params{};
-
- 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<bool>(config.is_password);
- params.cursor_at_beginning = static_cast<bool>(config.initial_cursor_position);
- params.value = static_cast<u8>(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(Core::System& system_, LibraryAppletMode applet_mode_,
+ Core::Frontend::SoftwareKeyboardApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
SoftwareKeyboard::~SoftwareKeyboard() = default;
void SoftwareKeyboard::Initialize() {
- complete = false;
- is_inline = false;
- initial_text.clear();
- final_data.clear();
-
Applet::Initialize();
- const auto keyboard_config_storage = broker.PopNormalDataToApplet();
- ASSERT(keyboard_config_storage != nullptr);
- const auto& keyboard_config = keyboard_config_storage->GetData();
-
- 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));
+ LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}",
+ applet_mode);
- const auto work_buffer_storage = broker.PopNormalDataToApplet();
- ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; });
- const auto& work_buffer = work_buffer_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);
- if (config.initial_string_size == 0)
- return;
+ swkbd_applet_version = SwkbdAppletVersion{common_args.library_version};
- std::vector<char16_t> 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());
+ 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;
+ }
}
bool SoftwareKeyboard::TransactionComplete() const {
@@ -95,106 +82,996 @@ bool SoftwareKeyboard::TransactionComplete() const {
}
ResultCode SoftwareKeyboard::GetStatus() const {
- return RESULT_SUCCESS;
+ return status;
}
void SoftwareKeyboard::ExecuteInteractive() {
- if (complete)
+ if (complete) {
return;
+ }
- const auto storage = broker.PopInteractiveDataToApplet();
- ASSERT(storage != nullptr);
- const auto data = storage->GetData();
- if (!is_inline) {
- const auto status = static_cast<bool>(data[0]);
- if (status == INTERACTIVE_STATUS_OK) {
- complete = true;
- } else {
- std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
- std::memcpy(string.data(), data.data() + 4, string.size() * 2);
- frontend.SendTextCheckDialog(
- Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()),
- [this] { broker.SignalStateChanged(); });
- }
+ if (is_background) {
+ ProcessInlineKeyboardRequest();
} else {
- Request request{};
- std::memcpy(&request, data.data(), sizeof(Request));
+ ProcessTextCheck();
+ }
+}
+
+void SoftwareKeyboard::Execute() {
+ if (complete) {
+ return;
+ }
+
+ if (is_background) {
+ return;
+ }
+
+ ShowNormalKeyboard();
+}
- switch (request) {
- case Request::Finalize:
- complete = true;
- broker.SignalStateChanged();
+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);
+ }
+}
+
+void SoftwareKeyboard::SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text,
+ s32 cursor_position) {
+ if (complete) {
+ return;
+ }
+
+ current_text = std::move(submitted_text);
+ current_cursor_position = cursor_position;
+
+ if (inline_use_utf8) {
+ switch (reply_type) {
+ case SwkbdReplyType::ChangedString:
+ reply_type = SwkbdReplyType::ChangedStringUtf8;
break;
- case Request::Calc: {
- broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1}));
- broker.SignalStateChanged();
+ case SwkbdReplyType::MovedCursor:
+ reply_type = SwkbdReplyType::MovedCursorUtf8;
+ break;
+ case SwkbdReplyType::DecidedEnter:
+ reply_type = SwkbdReplyType::DecidedEnterUtf8;
+ break;
+ default:
break;
}
+ }
+
+ 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:
- UNIMPLEMENTED_MSG("Request {:X} is not implemented", request);
break;
}
}
+
+ 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::Execute() {
- if (complete) {
- broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data)));
- broker.SignalStateChanged();
+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 parameters = ConvertToFrontendParameters(config, initial_text);
- if (!is_inline) {
- frontend.RequestText(
- [this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters);
+ const auto& work_buffer = work_buffer_storage->GetData();
+
+ std::vector<char16_t> 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);
+ }
+}
+
+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::WriteText(std::optional<std::u16string> text) {
- std::vector<u8> output_main(SWKBD_OUTPUT_BUFFER_SIZE);
+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));
- if (text.has_value()) {
- std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE);
+ SwkbdRequestCommand request_command;
- if (config.utf_8) {
- const u64 size = text->size() + sizeof(u64);
- const auto new_text = Common::UTF16ToUTF8(*text);
+ std::memcpy(&request_command, request_data.data(), sizeof(SwkbdRequestCommand));
- 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));
+ 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;
+ }
+}
- 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));
+void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result,
+ std::u16string submitted_text) {
+ std::vector<u8> out_data(sizeof(SwkbdResult) + STRING_BUFFER_SIZE);
- 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 (swkbd_config_common.use_utf8) {
+ std::string utf8_submitted_text = Common::UTF16ToUTF8(submitted_text);
- complete = !config.text_check;
- final_data = output_main;
+ LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-8 Submitted Text: {}", result,
+ utf8_submitted_text);
- if (complete) {
- broker.PushNormalDataFromApplet(
- std::make_shared<IStorage>(system, std::move(output_main)));
- broker.SignalStateChanged();
- } else {
- broker.PushInteractiveDataFromApplet(
- std::make_shared<IStorage>(system, std::move(output_sub)));
- }
+ std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
+ std::memcpy(out_data.data() + sizeof(SwkbdResult), utf8_submitted_text.data(),
+ utf8_submitted_text.size());
} else {
- output_main[0] = 1;
- complete = true;
- broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(output_main)));
- broker.SignalStateChanged();
+ 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<IStorage>(system, std::move(out_data)));
+
+ ExitKeyboard();
+}
+
+void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) {
+ current_text = std::move(submitted_text);
+
+ std::vector<u8> 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<IStorage>(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<s32>(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<u8>& request_data) {
+ LOG_DEBUG(Service_AM, "Processing Request: Finalize");
+
+ ChangeState(SwkbdState::NotInitialized);
+
+ ExitKeyboard();
+}
+
+void SoftwareKeyboard::RequestSetUserWordInfo(const std::vector<u8>& request_data) {
+ LOG_WARNING(Service_AM, "SetUserWordInfo is not implemented.");
+}
+
+void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector<u8>& request_data) {
+ LOG_WARNING(Service_AM, "SetCustomizeDic is not implemented.");
+}
+
+void SoftwareKeyboard::RequestCalc(const std::vector<u8>& 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<u8>& request_data) {
+ LOG_WARNING(Service_AM, "SetCustomizedDictionaries is not implemented.");
+}
+
+void SoftwareKeyboard::RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data) {
+ LOG_WARNING(Service_AM, "(STUBBED) Processing Request: UnsetCustomizedDictionaries");
+
+ ReplyUnsetCustomizedDictionaries();
+}
+
+void SoftwareKeyboard::RequestSetChangedStringV2Flag(const std::vector<u8>& 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<u8>& 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<u8> reply(REPLY_BASE_SIZE + 1);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyDefault() {
+ LOG_DEBUG(Service_AM, "Sending Reply: Default");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyChangedString() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ChangedString");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedString);
+
+ const SwkbdChangedStringArg changed_string_arg{
+ .text_length{static_cast<u32>(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<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyMovedCursor() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedCursor");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursor);
+
+ const SwkbdMovedCursorArg moved_cursor_arg{
+ .text_length{static_cast<u32>(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<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyMovedTab() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedTab");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedTabArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedTab);
+
+ const SwkbdMovedTabArg moved_tab_arg{
+ .text_length{static_cast<u32>(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<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyDecidedEnter() {
+ LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnter");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdDecidedEnterArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnter);
+
+ const SwkbdDecidedEnterArg decided_enter_arg{
+ .text_length{static_cast<u32>(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<IStorage>(system, std::move(reply)));
+
+ HideInlineKeyboard();
+}
+
+void SoftwareKeyboard::ReplyDecidedCancel() {
+ LOG_DEBUG(Service_AM, "Sending Reply: DecidedCancel");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+
+ HideInlineKeyboard();
+}
+
+void SoftwareKeyboard::ReplyChangedStringUtf8() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8");
+
+ std::vector<u8> 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<u32>(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<IStorage>(system, std::move(reply)));
}
+
+void SoftwareKeyboard::ReplyMovedCursorUtf8() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8");
+
+ std::vector<u8> 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<u32>(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<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyDecidedEnterUtf8() {
+ LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnterUtf8");
+
+ std::vector<u8> 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<u32>(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<IStorage>(system, std::move(reply)));
+
+ HideInlineKeyboard();
+}
+
+void SoftwareKeyboard::ReplyUnsetCustomizeDic() {
+ LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizeDic");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyReleasedUserWordInfo() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ReleasedUserWordInfo");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() {
+ LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizedDictionaries");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyChangedStringV2() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringV2");
+
+ std::vector<u8> 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<u32>(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<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyMovedCursorV2() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorV2");
+
+ std::vector<u8> 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<u32>(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<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyChangedStringUtf8V2() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8V2");
+
+ std::vector<u8> 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<u32>(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<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyMovedCursorUtf8V2() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8V2");
+
+ std::vector<u8> 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<u32>(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<IStorage>(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 1d260fef8..7c67b7574 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -1,20 +1,14 @@
-// Copyright 2018 yuzu emulator team
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
-#include <array>
-#include <string>
-#include <vector>
-
#include "common/common_funcs.h"
#include "common/common_types.h"
-#include "common/swap.h"
-#include "core/hle/service/am/am.h"
+#include "core/hle/result.h"
#include "core/hle/service/am/applets/applets.h"
-
-union ResultCode;
+#include "core/hle/service/am/applets/software_keyboard_types.h"
namespace Core {
class System;
@@ -22,45 +16,10 @@ 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<char16_t, 9> 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<char16_t, 65> header_text;
- std::array<char16_t, 129> sub_text;
- std::array<char16_t, 257> 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_,
- const Core::Frontend::SoftwareKeyboardApplet& frontend_);
+ explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
+ Core::Frontend::SoftwareKeyboardApplet& frontend_);
~SoftwareKeyboard() override;
void Initialize() override;
@@ -70,17 +29,138 @@ public:
void ExecuteInteractive() override;
void Execute() override;
- void WriteText(std::optional<std::u16string> text);
+ /**
+ * 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);
private:
- const Core::Frontend::SoftwareKeyboardApplet& frontend;
+ /// Initializes the normal software keyboard.
+ void InitializeForeground();
- KeyboardConfig config;
- std::u16string initial_text;
- bool complete = false;
- bool is_inline = false;
- std::vector<u8> final_data;
+ /// 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<u8>& request_data);
+ void RequestSetUserWordInfo(const std::vector<u8>& request_data);
+ void RequestSetCustomizeDic(const std::vector<u8>& request_data);
+ void RequestCalc(const std::vector<u8>& request_data);
+ void RequestSetCustomizedDictionaries(const std::vector<u8>& request_data);
+ void RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data);
+ void RequestSetChangedStringV2Flag(const std::vector<u8>& request_data);
+ void RequestSetMovedCursorV2Flag(const std::vector<u8>& 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();
+
+ 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;
+ 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};
};
} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/software_keyboard_types.h b/src/core/hle/service/am/applets/software_keyboard_types.h
new file mode 100644
index 000000000..21aa8e800
--- /dev/null
+++ b/src/core/hle/service/am/applets/software_keyboard_types.h
@@ -0,0 +1,295 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/swap.h"
+
+namespace Service::AM::Applets {
+
+constexpr std::size_t MAX_OK_TEXT_LENGTH = 8;
+constexpr std::size_t MAX_HEADER_TEXT_LENGTH = 64;
+constexpr std::size_t MAX_SUB_TEXT_LENGTH = 128;
+constexpr std::size_t MAX_GUIDE_TEXT_LENGTH = 256;
+constexpr std::size_t STRING_BUFFER_SIZE = 0x7D4;
+
+enum class SwkbdAppletVersion : u32_le {
+ Version5 = 0x5, // 1.0.0
+ Version65542 = 0x10006, // 2.0.0 - 2.3.0
+ Version196615 = 0x30007, // 3.0.0 - 3.0.2
+ Version262152 = 0x40008, // 4.0.0 - 4.1.0
+ Version327689 = 0x50009, // 5.0.0 - 5.1.0
+ Version393227 = 0x6000B, // 6.0.0 - 7.0.1
+ Version524301 = 0x8000D, // 8.0.0+
+};
+
+enum class SwkbdType : u32 {
+ Normal,
+ NumberPad,
+ Qwerty,
+ Unknown3,
+ Latin,
+ SimplifiedChinese,
+ TraditionalChinese,
+ Korean,
+};
+
+enum class SwkbdInitialCursorPosition : u32 {
+ Start,
+ End,
+};
+
+enum class SwkbdPasswordMode : u32 {
+ Disabled,
+ Enabled,
+};
+
+enum class SwkbdTextDrawType : u32 {
+ Line,
+ Box,
+ DownloadCode,
+};
+
+enum class SwkbdResult : u32 {
+ Ok,
+ Cancel,
+};
+
+enum class SwkbdTextCheckResult : u32 {
+ Success,
+ Failure,
+ Confirm,
+ Silent,
+};
+
+enum class SwkbdState : u32 {
+ NotInitialized = 0x0,
+ InitializedIsHidden = 0x1,
+ InitializedIsAppearing = 0x2,
+ InitializedIsShown = 0x3,
+ InitializedIsDisappearing = 0x4,
+};
+
+enum class SwkbdRequestCommand : u32 {
+ Finalize = 0x4,
+ SetUserWordInfo = 0x6,
+ SetCustomizeDic = 0x7,
+ Calc = 0xA,
+ SetCustomizedDictionaries = 0xB,
+ UnsetCustomizedDictionaries = 0xC,
+ SetChangedStringV2Flag = 0xD,
+ SetMovedCursorV2Flag = 0xE,
+};
+
+enum class SwkbdReplyType : u32 {
+ FinishedInitialize = 0x0,
+ Default = 0x1,
+ ChangedString = 0x2,
+ MovedCursor = 0x3,
+ MovedTab = 0x4,
+ DecidedEnter = 0x5,
+ DecidedCancel = 0x6,
+ ChangedStringUtf8 = 0x7,
+ MovedCursorUtf8 = 0x8,
+ DecidedEnterUtf8 = 0x9,
+ UnsetCustomizeDic = 0xA,
+ ReleasedUserWordInfo = 0xB,
+ UnsetCustomizedDictionaries = 0xC,
+ ChangedStringV2 = 0xD,
+ MovedCursorV2 = 0xE,
+ ChangedStringUtf8V2 = 0xF,
+ MovedCursorUtf8V2 = 0x10,
+};
+
+struct SwkbdKeyDisableFlags {
+ union {
+ u32 raw{};
+
+ BitField<1, 1, u32> space;
+ BitField<2, 1, u32> at;
+ BitField<3, 1, u32> percent;
+ BitField<4, 1, u32> slash;
+ BitField<5, 1, u32> backslash;
+ BitField<6, 1, u32> numbers;
+ BitField<7, 1, u32> download_code;
+ BitField<8, 1, u32> username;
+ };
+};
+static_assert(sizeof(SwkbdKeyDisableFlags) == 0x4, "SwkbdKeyDisableFlags has incorrect size.");
+
+struct SwkbdConfigCommon {
+ SwkbdType type{};
+ std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{};
+ char16_t left_optional_symbol_key{};
+ char16_t right_optional_symbol_key{};
+ bool use_prediction{};
+ INSERT_PADDING_BYTES(1);
+ SwkbdKeyDisableFlags key_disable_flags{};
+ SwkbdInitialCursorPosition initial_cursor_position{};
+ std::array<char16_t, MAX_HEADER_TEXT_LENGTH + 1> header_text{};
+ std::array<char16_t, MAX_SUB_TEXT_LENGTH + 1> sub_text{};
+ std::array<char16_t, MAX_GUIDE_TEXT_LENGTH + 1> guide_text{};
+ u32 max_text_length{};
+ u32 min_text_length{};
+ SwkbdPasswordMode password_mode{};
+ SwkbdTextDrawType text_draw_type{};
+ bool enable_return_button{};
+ bool use_utf8{};
+ bool use_blur_background{};
+ INSERT_PADDING_BYTES(1);
+ u32 initial_string_offset{};
+ u32 initial_string_length{};
+ u32 user_dictionary_offset{};
+ u32 user_dictionary_entries{};
+ bool use_text_check{};
+ INSERT_PADDING_BYTES(3);
+};
+static_assert(sizeof(SwkbdConfigCommon) == 0x3D4, "SwkbdConfigCommon has incorrect size.");
+
+#pragma pack(push, 4)
+// SwkbdAppletVersion 0x5, 0x10006
+struct SwkbdConfigOld {
+ INSERT_PADDING_WORDS(1);
+ VAddr text_check_callback{};
+};
+static_assert(sizeof(SwkbdConfigOld) == 0x3E0 - sizeof(SwkbdConfigCommon),
+ "SwkbdConfigOld has incorrect size.");
+
+// SwkbdAppletVersion 0x30007, 0x40008, 0x50009
+struct SwkbdConfigOld2 {
+ INSERT_PADDING_WORDS(1);
+ VAddr text_check_callback{};
+ std::array<u32, 8> text_grouping{};
+};
+static_assert(sizeof(SwkbdConfigOld2) == 0x400 - sizeof(SwkbdConfigCommon),
+ "SwkbdConfigOld2 has incorrect size.");
+
+// SwkbdAppletVersion 0x6000B, 0x8000D
+struct SwkbdConfigNew {
+ std::array<u32, 8> text_grouping{};
+ std::array<u64, 24> customized_dictionary_set_entries{};
+ u8 total_customized_dictionary_set_entries{};
+ bool disable_cancel_button{};
+ INSERT_PADDING_BYTES(18);
+};
+static_assert(sizeof(SwkbdConfigNew) == 0x4C8 - sizeof(SwkbdConfigCommon),
+ "SwkbdConfigNew has incorrect size.");
+#pragma pack(pop)
+
+struct SwkbdTextCheck {
+ SwkbdTextCheckResult text_check_result{};
+ std::array<char16_t, STRING_BUFFER_SIZE / 2> text_check_message{};
+};
+static_assert(sizeof(SwkbdTextCheck) == 0x7D8, "SwkbdTextCheck has incorrect size.");
+
+struct SwkbdCalcArgFlags {
+ union {
+ u64 raw{};
+
+ BitField<0, 1, u64> set_initialize_arg;
+ BitField<1, 1, u64> set_volume;
+ BitField<2, 1, u64> appear;
+ BitField<3, 1, u64> set_input_text;
+ BitField<4, 1, u64> set_cursor_position;
+ BitField<5, 1, u64> set_utf8_mode;
+ BitField<6, 1, u64> unset_customize_dic;
+ BitField<7, 1, u64> disappear;
+ BitField<8, 1, u64> unknown;
+ BitField<9, 1, u64> set_key_top_translate_scale;
+ BitField<10, 1, u64> unset_user_word_info;
+ BitField<11, 1, u64> set_disable_hardware_keyboard;
+ };
+};
+static_assert(sizeof(SwkbdCalcArgFlags) == 0x8, "SwkbdCalcArgFlags has incorrect size.");
+
+struct SwkbdInitializeArg {
+ u32 unknown{};
+ bool library_applet_mode_flag{};
+ bool is_above_hos_500{};
+ INSERT_PADDING_BYTES(2);
+};
+static_assert(sizeof(SwkbdInitializeArg) == 0x8, "SwkbdInitializeArg has incorrect size.");
+
+struct SwkbdAppearArg {
+ SwkbdType type{};
+ std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{};
+ char16_t left_optional_symbol_key{};
+ char16_t right_optional_symbol_key{};
+ bool use_prediction{};
+ bool disable_cancel_button{};
+ SwkbdKeyDisableFlags key_disable_flags{};
+ u32 max_text_length{};
+ u32 min_text_length{};
+ bool enable_return_button{};
+ INSERT_PADDING_BYTES(3);
+ u32 flags{};
+ INSERT_PADDING_WORDS(6);
+};
+static_assert(sizeof(SwkbdAppearArg) == 0x48, "SwkbdAppearArg has incorrect size.");
+
+struct SwkbdCalcArg {
+ u32 unknown{};
+ u16 calc_arg_size{};
+ INSERT_PADDING_BYTES(2);
+ SwkbdCalcArgFlags flags{};
+ SwkbdInitializeArg initialize_arg{};
+ f32 volume{};
+ s32 cursor_position{};
+ SwkbdAppearArg appear_arg{};
+ std::array<char16_t, 0x1FA> input_text{};
+ bool utf8_mode{};
+ INSERT_PADDING_BYTES(1);
+ bool enable_backspace_button{};
+ INSERT_PADDING_BYTES(3);
+ bool key_top_as_floating{};
+ bool footer_scalable{};
+ bool alpha_enabled_in_input_mode{};
+ u8 input_mode_fade_type{};
+ bool disable_touch{};
+ bool disable_hardware_keyboard{};
+ INSERT_PADDING_BYTES(8);
+ f32 key_top_scale_x{};
+ f32 key_top_scale_y{};
+ f32 key_top_translate_x{};
+ f32 key_top_translate_y{};
+ f32 key_top_bg_alpha{};
+ f32 footer_bg_alpha{};
+ f32 balloon_scale{};
+ INSERT_PADDING_WORDS(4);
+ u8 se_group{};
+ INSERT_PADDING_BYTES(3);
+};
+static_assert(sizeof(SwkbdCalcArg) == 0x4A0, "SwkbdCalcArg has incorrect size.");
+
+struct SwkbdChangedStringArg {
+ u32 text_length{};
+ s32 dictionary_start_cursor_position{};
+ s32 dictionary_end_cursor_position{};
+ s32 cursor_position{};
+};
+static_assert(sizeof(SwkbdChangedStringArg) == 0x10, "SwkbdChangedStringArg has incorrect size.");
+
+struct SwkbdMovedCursorArg {
+ u32 text_length{};
+ s32 cursor_position{};
+};
+static_assert(sizeof(SwkbdMovedCursorArg) == 0x8, "SwkbdMovedCursorArg has incorrect size.");
+
+struct SwkbdMovedTabArg {
+ u32 text_length{};
+ s32 cursor_position{};
+};
+static_assert(sizeof(SwkbdMovedTabArg) == 0x8, "SwkbdMovedTabArg has incorrect size.");
+
+struct SwkbdDecidedEnterArg {
+ u32 text_length{};
+};
+static_assert(sizeof(SwkbdDecidedEnterArg) == 0x4, "SwkbdDecidedEnterArg has incorrect size.");
+
+} // 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 2ab420789..2404921fd 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -208,8 +208,9 @@ void ExtractSharedFonts(Core::System& system) {
} // namespace
-WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_)
- : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {}
+WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::WebBrowserApplet& frontend_)
+ : Applet{system_, applet_mode_}, 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 04c274754..21fd910c2 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -25,7 +25,8 @@ namespace Service::AM::Applets {
class WebBrowser final : public Applet {
public:
- WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_);
+ WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::WebBrowserApplet& frontend_);
~WebBrowser() override;
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 0f51e5871..75867e349 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -7,6 +7,7 @@
#include <vector>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/common_funcs.h"
#include "core/file_sys/content_archive.h"
@@ -21,7 +22,6 @@
#include "core/hle/kernel/process.h"
#include "core/hle/service/aoc/aoc_u.h"
#include "core/loader/loader.h"
-#include "core/settings.h"
namespace Service::AOC {
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp
index 03636642b..00c174bb0 100644
--- a/src/core/hle/service/apm/controller.cpp
+++ b/src/core/hle/service/apm/controller.cpp
@@ -7,9 +7,9 @@
#include <utility>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hle/service/apm/controller.h"
-#include "core/settings.h"
namespace Service::APM {
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
index e43f3f47f..78c047bd2 100644
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ b/src/core/hle/service/bcat/backend/boxcat.cpp
@@ -9,6 +9,7 @@
#include "common/hex_util.h"
#include "common/logging/backend.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_libzip.h"
@@ -16,7 +17,6 @@
#include "core/frontend/applets/error.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/bcat/backend/boxcat.h"
-#include "core/settings.h"
namespace Service::BCAT {
namespace {
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index b68e2c345..c7dd04a6e 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -7,6 +7,7 @@
#include "backend/boxcat.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/file_sys/vfs.h"
@@ -18,7 +19,6 @@
#include "core/hle/service/bcat/bcat.h"
#include "core/hle/service/bcat/module.h"
#include "core/hle/service/filesystem/filesystem.h"
-#include "core/settings.h"
namespace Service::BCAT {
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index b15c737e1..72ad273b2 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -6,6 +6,7 @@
#include "common/assert.h"
#include "common/file_util.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/bis_factory.h"
#include "core/file_sys/card_image.h"
@@ -26,7 +27,6 @@
#include "core/hle/service/filesystem/fsp_pr.h"
#include "core/hle/service/filesystem/fsp_srv.h"
#include "core/loader/loader.h"
-#include "core/settings.h"
namespace Service::FileSystem {
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp
index 322125135..7b1c6677c 100644
--- a/src/core/hle/service/glue/arp.cpp
+++ b/src/core/hle/service/glue/arp.cpp
@@ -157,9 +157,9 @@ class IRegistrar final : public ServiceFramework<IRegistrar> {
friend class ARP_W;
public:
- explicit IRegistrar(
- Core::System& system_,
- std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issuer)
+ using IssuerFn = std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)>;
+
+ explicit IRegistrar(Core::System& system_, IssuerFn&& issuer)
: ServiceFramework{system_, "IRegistrar"}, issue_process_id{std::move(issuer)} {
// clang-format off
static const FunctionInfo functions[] = {
@@ -238,9 +238,9 @@ private:
rb.Push(RESULT_SUCCESS);
}
- std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issue_process_id;
+ IssuerFn issue_process_id;
bool issued = false;
- ApplicationLaunchProperty launch;
+ ApplicationLaunchProperty launch{};
std::vector<u8> control;
};
diff --git a/src/core/hle/service/glue/ectx.cpp b/src/core/hle/service/glue/ectx.cpp
new file mode 100644
index 000000000..249c6f003
--- /dev/null
+++ b/src/core/hle/service/glue/ectx.cpp
@@ -0,0 +1,22 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/glue/ectx.h"
+
+namespace Service::Glue {
+
+ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateContextRegistrar"},
+ {1, nullptr, "CommitContext"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ECTX_AW::~ECTX_AW() = default;
+
+} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/ectx.h b/src/core/hle/service/glue/ectx.h
new file mode 100644
index 000000000..b275e808a
--- /dev/null
+++ b/src/core/hle/service/glue/ectx.h
@@ -0,0 +1,21 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::Glue {
+
+class ECTX_AW final : public ServiceFramework<ECTX_AW> {
+public:
+ explicit ECTX_AW(Core::System& system_);
+ ~ECTX_AW() override;
+};
+
+} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp
index 4eafbe5fa..a08dc9758 100644
--- a/src/core/hle/service/glue/glue.cpp
+++ b/src/core/hle/service/glue/glue.cpp
@@ -6,6 +6,7 @@
#include "core/core.h"
#include "core/hle/service/glue/arp.h"
#include "core/hle/service/glue/bgtc.h"
+#include "core/hle/service/glue/ectx.h"
#include "core/hle/service/glue/glue.h"
namespace Service::Glue {
@@ -20,6 +21,9 @@ void InstallInterfaces(Core::System& system) {
// BackGround Task Controller
std::make_shared<BGTC_T>(system)->InstallAsService(system.ServiceManager());
std::make_shared<BGTC_SC>(system)->InstallAsService(system.ServiceManager());
+
+ // Error Context
+ std::make_shared<ECTX_AW>(system)->InstallAsService(system.ServiceManager());
}
} // namespace Service::Glue
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index ad251ed4a..a460f2f79 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -4,9 +4,9 @@
#include <cstring>
#include "common/common_types.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
-#include "core/settings.h"
namespace Service::HID {
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 555b29d76..0593d7d39 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -8,10 +8,10 @@
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/settings.h"
namespace Service::HID {
class Controller_DebugPad final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 93c43a203..155808f6a 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -5,10 +5,10 @@
#include <cstring>
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
#include "core/hle/service/hid/controllers/gesture.h"
-#include "core/settings.h"
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index c4a59147d..18b76038f 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -4,9 +4,9 @@
#include <cstring>
#include "common/common_types.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hle/service/hid/controllers/keyboard.h"
-#include "core/settings.h"
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index b5b281752..e72948591 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -8,10 +8,10 @@
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/settings.h"
namespace Service::HID {
class Controller_Keyboard final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 3b432a36e..0ec0c2b94 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -7,10 +7,10 @@
#include <array>
#include "common/bit_field.h"
#include "common/common_types.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/settings.h"
namespace Service::HID {
class Controller_Mouse final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 673db68c7..113a41254 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -9,6 +9,7 @@
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/frontend/input.h"
@@ -17,7 +18,6 @@
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/hid/controllers/npad.h"
-#include "core/settings.h"
namespace Service::HID {
constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
@@ -147,7 +147,7 @@ bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
device_handle.device_index < DeviceIndex::MaxDeviceIndex;
}
-Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {
+Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system) {
latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE});
}
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 873a0a1e2..c3b07bd41 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -8,10 +8,10 @@
#include <atomic>
#include "common/bit_field.h"
#include "common/common_types.h"
+#include "common/settings.h"
#include "core/frontend/input.h"
#include "core/hle/kernel/object.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/settings.h"
namespace Kernel {
class KEvent;
@@ -587,6 +587,5 @@ private:
std::array<ControllerPad, 10> npad_pad_states{};
std::array<TriggerState, 10> npad_trigger_states{};
bool is_in_lr_assignment_mode{false};
- Core::System& system;
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index be60492a4..b5f8077be 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -6,11 +6,11 @@
#include <cstring>
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
-#include "core/settings.h"
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index a1a779cc0..2aa1942cb 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -5,6 +5,7 @@
#include <array>
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
@@ -18,12 +19,12 @@
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/transfer_memory.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/irs.h"
#include "core/hle/service/hid/xcd.h"
#include "core/hle/service/service.h"
-#include "core/settings.h"
#include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
@@ -1484,7 +1485,43 @@ void Hid::StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
}
void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto t_mem_1_size{rp.Pop<u64>()};
+ const auto t_mem_2_size{rp.Pop<u64>()};
+ const auto t_mem_1_handle{ctx.GetCopyHandle(0)};
+ const auto t_mem_2_handle{ctx.GetCopyHandle(1)};
+
+ ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes");
+ ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes");
+
+ auto t_mem_1 =
+ system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(t_mem_1_handle);
+
+ if (t_mem_1 == nullptr) {
+ LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_UNKNOWN);
+ return;
+ }
+
+ auto t_mem_2 =
+ system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(t_mem_2_handle);
+
+ if (t_mem_2 == nullptr) {
+ LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_UNKNOWN);
+ return;
+ }
+
+ ASSERT_MSG(t_mem_1->GetSize() == 0x1000, "t_mem_1 has incorrect size");
+ ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size");
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "
+ "applet_resource_user_id={}",
+ t_mem_1_handle, t_mem_2_handle, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp
index f4490f3d9..e11a0c45a 100644
--- a/src/core/hle/service/lbl/lbl.cpp
+++ b/src/core/hle/service/lbl/lbl.cpp
@@ -79,7 +79,6 @@ private:
}
void GetCurrentBrightnessSetting(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
auto brightness = current_brightness;
if (!std::isfinite(brightness)) {
LOG_ERROR(Service_LBL, "Brightness is infinite!");
@@ -272,7 +271,6 @@ private:
}
void GetCurrentBrightnessSettingForVrMode(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
auto brightness = current_vr_brightness;
if (!std::isfinite(brightness)) {
LOG_ERROR(Service_LBL, "Brightness is infinite!");
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index 7d7542fc2..9bcf8870d 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -46,7 +46,7 @@ struct hash<Service::LM::LogPacketHeaderEntry> {
boost::hash_combine(seed, k.severity);
boost::hash_combine(seed, k.verbosity);
return seed;
- };
+ }
};
} // namespace std
@@ -95,7 +95,7 @@ private:
std::memcpy(&header, data.data(), sizeof(LogPacketHeader));
offset += sizeof(LogPacketHeader);
- LogPacketHeaderEntry entry{
+ const LogPacketHeaderEntry entry{
.pid = header.pid,
.tid = header.tid,
.severity = header.severity,
@@ -105,16 +105,17 @@ private:
if (True(header.flags & LogPacketFlags::Head)) {
std::vector<u8> tmp(data.size() - sizeof(LogPacketHeader));
std::memcpy(tmp.data(), data.data() + offset, tmp.size());
- entries[entry] = std::move(tmp);
+ entries.insert_or_assign(entry, std::move(tmp));
} else {
+ const auto entry_iter = entries.find(entry);
+
// Append to existing entry
- if (!entries.contains(entry)) {
+ if (entry_iter == entries.cend()) {
LOG_ERROR(Service_LM, "Log entry does not exist!");
return;
}
- std::vector<u8> tmp(data.size() - sizeof(LogPacketHeader));
- auto& existing_entry = entries[entry];
+ auto& existing_entry = entry_iter->second;
const auto base = existing_entry.size();
existing_entry.resize(base + (data.size() - sizeof(LogPacketHeader)));
std::memcpy(existing_entry.data() + base, data.data() + offset,
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index 6ab35de47..44a5d5789 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -5,12 +5,12 @@
#include <memory>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/nfc/nfc.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
-#include "core/settings.h"
namespace Service::NFC {
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index afb3342d6..9f110df8e 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/settings.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
@@ -10,7 +11,6 @@
#include "core/hle/service/nifm/nifm.h"
#include "core/hle/service/service.h"
#include "core/network/network.h"
-#include "core/settings.h"
namespace Service::NIFM {
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 5fe7a9189..e373609a1 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
@@ -14,7 +15,6 @@
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/ns/pl_u.h"
#include "core/hle/service/set/set.h"
-#include "core/settings.h"
namespace Service::NS {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index c8031970b..e2f671d8e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -31,14 +31,8 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
return SetSubmitTimeout(input, output);
case 0x9:
return MapBuffer(input, output);
- case 0xa: {
- if (command.length == 0x1c) {
- LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
- Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}};
- system.GPU().PushCommandBuffer(cmdlist);
- }
+ case 0xa:
return UnmapBuffer(input, output);
- }
default:
break;
}
@@ -70,6 +64,10 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>&
}
void nvhost_nvdec::OnOpen(DeviceFD fd) {}
-void nvhost_nvdec::OnClose(DeviceFD fd) {}
+
+void nvhost_nvdec::OnClose(DeviceFD fd) {
+ LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
+ system.GPU().ClearCdmaInstance();
+}
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index 0421fb956..301efe8a1 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -29,13 +29,8 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i
return GetWaitbase(input, output);
case 0x9:
return MapBuffer(input, output);
- case 0xa: {
- if (command.length == 0x1c) {
- Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}};
- system.GPU().PushCommandBuffer(cmdlist);
- }
+ case 0xa:
return UnmapBuffer(input, output);
- }
default:
break;
}
@@ -69,6 +64,9 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& i
}
void nvhost_vic::OnOpen(DeviceFD fd) {}
-void nvhost_vic::OnClose(DeviceFD fd) {}
+
+void nvhost_vic::OnClose(DeviceFD fd) {
+ system.GPU().ClearCdmaInstance();
+}
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index ac2906e5b..539b02bc4 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -9,6 +9,7 @@
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "common/thread.h"
#include "core/core.h"
#include "core/core_timing.h"
@@ -23,7 +24,6 @@
#include "core/hle/service/vi/display/vi_display.h"
#include "core/hle/service/vi/layer/vi_layer.h"
#include "core/perf_stats.h"
-#include "core/settings.h"
#include "video_core/renderer_base.h"
namespace Service::NVFlinger {
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index aec399076..41a502d8d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -6,6 +6,7 @@
#include <fmt/format.h>
#include "common/assert.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/ipc.h"
@@ -70,7 +71,6 @@
#include "core/hle/service/vi/vi.h"
#include "core/hle/service/wlan/wlan.h"
#include "core/reporter.h"
-#include "core/settings.h"
namespace Service {
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index d953b4303..fbdc4793d 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -6,9 +6,9 @@
#include <array>
#include <chrono>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/set/set.h"
-#include "core/settings.h"
namespace Service::Set {
namespace {
@@ -104,9 +104,10 @@ void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) {
layout = key_code->second;
}
+ ctx.WriteBuffer(layout);
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
- ctx.WriteBuffer(layout);
}
} // Anonymous namespace
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp
index 6903dd534..b1552c3f0 100644
--- a/src/core/hle/service/spl/module.cpp
+++ b/src/core/hle/service/spl/module.cpp
@@ -9,11 +9,11 @@
#include <functional>
#include <vector>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/spl/csrng.h"
#include "core/hle/service/spl/module.h"
#include "core/hle/service/spl/spl.h"
-#include "core/settings.h"
namespace Service::SPL {
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 63e0247de..32f372d71 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -294,16 +294,17 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
return;
}
+ ctx.WriteBuffer(clock_snapshot);
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
- ctx.WriteBuffer(clock_snapshot);
}
void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto type{rp.PopEnum<Clock::TimeType>()};
- rp.AlignWithPadding();
+ rp.Skip(1, false);
const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()};
const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()};
@@ -319,9 +320,10 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques
return;
}
+ ctx.WriteBuffer(clock_snapshot);
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
- ctx.WriteBuffer(clock_snapshot);
}
void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
index 51becd074..f89c5aaad 100644
--- a/src/core/hle/service/time/time_manager.cpp
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -5,12 +5,12 @@
#include <chrono>
#include <ctime>
+#include "common/settings.h"
#include "common/time_zone.h"
#include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h"
#include "core/hle/service/time/local_system_clock_context_writer.h"
#include "core/hle/service/time/network_system_clock_context_writer.h"
#include "core/hle/service/time/time_manager.h"
-#include "core/settings.h"
namespace Service::Time {
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp
index 4177d0a41..3c8e71a3c 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -5,6 +5,7 @@
#include <sstream>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/time_zone.h"
#include "core/core.h"
#include "core/file_sys/content_archive.h"
@@ -15,7 +16,6 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/time/time_manager.h"
#include "core/hle/service/time/time_zone_content_manager.h"
-#include "core/settings.h"
namespace Service::Time::TimeZone {
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
index 3117627cf..19d7a1a0c 100644
--- a/src/core/hle/service/time/time_zone_service.cpp
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -140,11 +140,12 @@ void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) {
return;
}
+ ctx.WriteBuffer(posix_time);
+
// TODO(bunnei): Handle multiple times
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(1); // Number of times we're returning
- ctx.WriteBuffer(posix_time);
}
void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
@@ -163,10 +164,11 @@ void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
return;
}
+ ctx.WriteBuffer(posix_time);
+
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(1); // Number of times we're returning
- ctx.WriteBuffer(posix_time);
}
} // namespace Service::Time
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index a1a7ac987..7ae07d072 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -15,6 +15,7 @@
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "common/math_util.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
@@ -30,7 +31,6 @@
#include "core/hle/service/vi/vi_m.h"
#include "core/hle/service/vi/vi_s.h"
#include "core/hle/service/vi/vi_u.h"
-#include "core/settings.h"
namespace Service::VI {
@@ -1129,9 +1129,11 @@ private:
}
NativeWindow native_window{*buffer_queue_id};
+ const auto buffer_size = ctx.WriteBuffer(native_window.Serialize());
+
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
- rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
+ rb.Push<u64>(buffer_size);
}
void CloseLayer(Kernel::HLERequestContext& ctx) {
@@ -1173,10 +1175,12 @@ private:
}
NativeWindow native_window{*buffer_queue_id};
+ const auto buffer_size = ctx.WriteBuffer(native_window.Serialize());
+
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.Push(*layer_id);
- rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
+ rb.Push<u64>(buffer_size);
}
void DestroyStrayLayer(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp
index 3f4ba233d..55e6de794 100644
--- a/src/core/loader/kip.cpp
+++ b/src/core/loader/kip.cpp
@@ -68,7 +68,8 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process,
FileSys::ProgramMetadata metadata;
metadata.LoadManual(kip->Is64Bit(), address_space, kip->GetMainThreadPriority(),
kip->GetMainThreadCpuCore(), kip->GetMainThreadStackSize(),
- kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, kip->GetKernelCapabilities());
+ kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, 0x1FE00000,
+ kip->GetKernelCapabilities());
const VAddr base_address = process.PageTable().GetCodeRegionStart();
Kernel::CodeSet codeset;
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 14618cb40..0115ed0c4 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -9,6 +9,7 @@
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
@@ -22,7 +23,6 @@
#include "core/loader/nro.h"
#include "core/loader/nso.h"
#include "core/memory.h"
-#include "core/settings.h"
namespace Loader {
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index cbd048695..0c83dd666 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -11,6 +11,7 @@
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/lz4_compression.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/core.h"
#include "core/file_sys/patch_manager.h"
@@ -20,7 +21,6 @@
#include "core/hle/kernel/process.h"
#include "core/loader/nso.h"
#include "core/memory.h"
-#include "core/settings.h"
namespace Loader {
namespace {
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index b93396a80..c92337079 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -13,8 +13,8 @@
#include <fmt/format.h>
#include "common/file_util.h"
#include "common/math_util.h"
+#include "common/settings.h"
#include "core/perf_stats.h"
-#include "core/settings.h"
using namespace std::chrono_literals;
using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>;
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index 74fb32814..311d4dda8 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -14,6 +14,7 @@
#include "common/file_util.h"
#include "common/hex_util.h"
#include "common/scm_rev.h"
+#include "common/settings.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/hle_ipc.h"
@@ -22,7 +23,6 @@
#include "core/hle/result.h"
#include "core/memory.h"
#include "core/reporter.h"
-#include "core/settings.h"
namespace {
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index d11b15f38..6dcff5400 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -12,10 +12,10 @@
#include "common/file_util.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/loader/loader.h"
-#include "core/settings.h"
#include "core/telemetry_session.h"
#ifdef ENABLE_WEB_SERVICE
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 38ab31898..de53e1fda 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -9,8 +9,6 @@ add_library(input_common STATIC
motion_from_button.h
motion_input.cpp
motion_input.h
- settings.cpp
- settings.h
touch_from_button.cpp
touch_from_button.h
gcadapter/gc_adapter.cpp
@@ -64,7 +62,7 @@ else()
)
endif()
-if(SDL2_FOUND)
+if (ENABLE_SDL2)
target_sources(input_common PRIVATE
sdl/sdl_impl.cpp
sdl/sdl_impl.h
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
index 770893687..f8ec179d0 100755
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/analog_from_button.cpp
@@ -7,7 +7,7 @@
#include <cmath>
#include <thread>
#include "common/math_util.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "input_common/analog_from_button.h"
namespace InputCommon {
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index d80195c82..ec3167bea 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -16,8 +16,8 @@
#include "common/logging/log.h"
#include "common/param_package.h"
+#include "common/settings_input.h"
#include "input_common/gcadapter/gc_adapter.h"
-#include "input_common/settings.h"
namespace GCAdapter {
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
index 329e416c7..fff1c6b45 100644
--- a/src/input_common/mouse/mouse_input.cpp
+++ b/src/input_common/mouse/mouse_input.cpp
@@ -2,7 +2,7 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include "core/settings.h"
+#include "common/settings.h"
#include "input_common/mouse/mouse_input.h"
namespace MouseInput {
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index 0e1db54fb..d96104a4e 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -5,8 +5,8 @@
#include <mutex>
#include <utility>
+#include "common/settings.h"
#include "common/threadsafe_queue.h"
-#include "core/settings.h"
#include "input_common/mouse/mouse_input.h"
#include "input_common/mouse/mouse_poller.h"
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index f67de37e3..f682a6db4 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -17,14 +17,24 @@
#include <unordered_map>
#include <utility>
#include <vector>
+
+// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+#endif
#include <SDL.h>
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
#include "common/logging/log.h"
#include "common/param_package.h"
+#include "common/settings_input.h"
#include "common/threadsafe_queue.h"
#include "core/frontend/input.h"
#include "input_common/motion_input.h"
#include "input_common/sdl/sdl_impl.h"
-#include "input_common/settings.h"
namespace InputCommon::SDL {
@@ -761,7 +771,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
for (const auto& joystick : value) {
if (auto* const controller = joystick->GetSDLGameController()) {
std::string name =
- fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort());
+ fmt::format("{} {}", GetControllerName(controller), joystick->GetPort());
devices.emplace_back(Common::ParamPackage{
{"class", "sdl"},
{"display", std::move(name)},
@@ -782,6 +792,17 @@ std::vector<Common::ParamPackage> 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) {
@@ -930,16 +951,19 @@ 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<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>;
- 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},
+ 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},
{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 08044b00d..8b7363f56 100644
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/sdl/sdl_impl.h
@@ -14,6 +14,7 @@
#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;
@@ -64,6 +65,9 @@ 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/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp
index ffbe4f2ed..e94ba197b 100644
--- a/src/input_common/touch_from_button.cpp
+++ b/src/input_common/touch_from_button.cpp
@@ -2,8 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/settings.h"
#include "core/frontend/framebuffer_layout.h"
-#include "core/settings.h"
#include "input_common/touch_from_button.h"
namespace InputCommon {
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index e72df924b..8a38a380d 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -9,7 +9,7 @@
#include <thread>
#include <boost/asio.hpp>
#include "common/logging/log.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "input_common/udp/client.h"
#include "input_common/udp/protocol.h"
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 4de1e37e5..32dcbd693 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -20,8 +20,8 @@
#include "common/div_ceil.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "core/memory.h"
-#include "core/settings.h"
#include "video_core/buffer_cache/buffer_base.h"
#include "video_core/delayed_destruction_ring.h"
#include "video_core/dirty_flags.h"
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp
index a2f19559f..2ee980bab 100644
--- a/src/video_core/engines/maxwell_dma.cpp
+++ b/src/video_core/engines/maxwell_dma.cpp
@@ -4,8 +4,8 @@
#include "common/assert.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/engines/maxwell_dma.h"
#include "video_core/memory_manager.h"
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 009c6f574..a38024242 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -6,13 +6,13 @@
#include "common/assert.h"
#include "common/microprofile.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/frontend/emu_window.h"
#include "core/hardware_interrupt_manager.h"
#include "core/memory.h"
-#include "core/settings.h"
#include "video_core/engines/fermi_2d.h"
#include "video_core/engines/kepler_compute.h"
#include "video_core/engines/kepler_memory.h"
@@ -480,11 +480,7 @@ void GPU::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) {
if (!use_nvdec) {
return;
}
- // This condition fires when a video stream ends, clear all intermediary data
- if (entries[0].raw == 0xDEADB33F) {
- cdma_pusher.reset();
- return;
- }
+
if (!cdma_pusher) {
cdma_pusher = std::make_unique<Tegra::CDmaPusher>(*this);
}
@@ -496,6 +492,10 @@ void GPU::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) {
cdma_pusher->ProcessEntries(std::move(entries));
}
+void GPU::ClearCdmaInstance() {
+ cdma_pusher.reset();
+}
+
void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
gpu_thread.SwapBuffers(framebuffer);
}
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index ecab35d3b..8669e9940 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -324,6 +324,9 @@ public:
/// Push GPU command buffer entries to be processed
void PushCommandBuffer(Tegra::ChCommandHeaderList& entries);
+ /// Frees the CDMAPusher instance to free up resources
+ void ClearCdmaInstance();
+
/// Swap buffers (render frame)
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 7addfbc7b..cd1fbb9bf 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -5,10 +5,10 @@
#include "common/assert.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "common/thread.h"
#include "core/core.h"
#include "core/frontend/emu_window.h"
-#include "core/settings.h"
#include "video_core/dma_pusher.h"
#include "video_core/gpu.h"
#include "video_core/gpu_thread.h"
diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp
index cd21a2112..d7fabe605 100644
--- a/src/video_core/macro/macro.cpp
+++ b/src/video_core/macro/macro.cpp
@@ -6,7 +6,7 @@
#include <boost/container_hash/hash.hpp>
#include "common/assert.h"
#include "common/logging/log.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/macro/macro.h"
#include "video_core/macro/macro_hle.h"
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index 639d7ce7e..aac851253 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -16,8 +16,8 @@
#include <vector>
#include "common/assert.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index a93a1732c..c9a360aaf 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -3,8 +3,8 @@
// Refer to the license.txt file included.
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/frontend/emu_window.h"
-#include "core/settings.h"
#include "video_core/renderer_base.h"
namespace VideoCore {
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index 5776fccdc..b113f54db 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -16,7 +16,7 @@
#include "common/logging/log.h"
#include "common/scope_exit.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "video_core/renderer_opengl/gl_device.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 4610fd160..0863904e9 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -17,10 +17,10 @@
#include "common/math_util.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/hle/kernel/process.h"
#include "core/memory.h"
-#include "core/settings.h"
#include "video_core/engines/kepler_compute.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/engines/shader_type.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
index 955b2abc4..97fb11ac6 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
@@ -12,10 +12,10 @@
#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
+#include "common/settings.h"
#include "common/zstd_compression.h"
#include "core/core.h"
#include "core/hle/kernel/process.h"
-#include "core/settings.h"
#include "video_core/engines/shader_type.h"
#include "video_core/renderer_opengl/gl_shader_cache.h"
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 9d2acd4d9..cc2e499f9 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -13,13 +13,13 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
+#include "common/settings.h"
#include "common/telemetry.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
#include "core/memory.h"
#include "core/perf_stats.h"
-#include "core/settings.h"
#include "core/telemetry_session.h"
#include "video_core/host_shaders/opengl_present_frag.h"
#include "video_core/host_shaders/opengl_present_vert.h"
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 14e5f36e2..2e0cf4232 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -13,11 +13,11 @@
#include <fmt/format.h>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/telemetry.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
-#include "core/settings.h"
#include "core/telemetry_session.h"
#include "video_core/gpu.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
index 56ec5e380..db78ce3d9 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
@@ -5,7 +5,7 @@
#include <atomic>
#include <chrono>
-#include "core/settings.h"
+#include "common/settings.h"
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index df5b7b172..e9a0e7811 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -13,8 +13,8 @@
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "video_core/engines/kepler_compute.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_vulkan/blit_image.h"
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index bc2a53841..017348e05 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -417,7 +417,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
};
}
-[[nodiscard]] constexpr SwizzleSource ConvertGreenRed(SwizzleSource value) {
+[[nodiscard]] SwizzleSource ConvertGreenRed(SwizzleSource value) {
switch (value) {
case SwizzleSource::G:
return SwizzleSource::R;
@@ -426,6 +426,17 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
}
}
+[[nodiscard]] SwizzleSource SwapBlueRed(SwizzleSource value) {
+ switch (value) {
+ case SwizzleSource::R:
+ return SwizzleSource::B;
+ case SwizzleSource::B:
+ return SwizzleSource::R;
+ default:
+ return value;
+ }
+}
+
void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage image,
VkImageAspectFlags aspect_mask, bool is_initialized,
std::span<const VkBufferImageCopy> copies) {
@@ -543,6 +554,15 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
};
}
+[[nodiscard]] bool IsFormatFlipped(PixelFormat format) {
+ switch (format) {
+ case PixelFormat::A1B5G5R5_UNORM:
+ return true;
+ default:
+ return false;
+ }
+}
+
struct RangedBarrierRange {
u32 min_mip = std::numeric_limits<u32>::max();
u32 max_mip = std::numeric_limits<u32>::min();
@@ -948,6 +968,9 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
};
if (!info.IsRenderTarget()) {
swizzle = info.Swizzle();
+ if (IsFormatFlipped(format)) {
+ std::ranges::transform(swizzle, swizzle.begin(), SwapBlueRed);
+ }
if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0) {
std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed);
}
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp
index f89a40b4c..e8d632f9e 100644
--- a/src/video_core/texture_cache/image_view_base.cpp
+++ b/src/video_core/texture_cache/image_view_base.cpp
@@ -5,7 +5,7 @@
#include <algorithm>
#include "common/assert.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "video_core/compatible_formats.h"
#include "video_core/surface.h"
#include "video_core/texture_cache/formatter.h"
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index 0ab297413..8c4a5523b 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -1139,7 +1139,7 @@ void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase*
dst_info.format = src->info.format;
}
if (!src && dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) {
- src_info.format = src->info.format;
+ src_info.format = dst->info.format;
}
}
diff --git a/src/video_core/textures/texture.cpp b/src/video_core/textures/texture.cpp
index ae5621a7d..a552543ed 100644
--- a/src/video_core/textures/texture.cpp
+++ b/src/video_core/textures/texture.cpp
@@ -6,7 +6,7 @@
#include <array>
#include "common/cityhash.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "video_core/textures/texture.h"
using Tegra::Texture::TICEntry;
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index e1b38c6ac..3b575db4d 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -5,8 +5,8 @@
#include <memory>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 230b8717b..64206b3d2 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -12,7 +12,7 @@
#include <vector>
#include "common/assert.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "video_core/vulkan_common/nsight_aftermath_tracker.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index b025ced1c..cc0790e07 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -18,6 +18,7 @@ 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
@@ -143,6 +144,9 @@ 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 8ee03ddb3..085688cd4 100644
--- 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<void()> finished) const {
callback = std::move(finished);
emit MainWindowDisplayError(
- tr("An error has occurred.\nPlease try again or contact the developer of the "
- "software.\n\nError Code: %1-%2 (0x%3)")
+ tr("Error Code: %1-%2 (0x%3)")
.arg(static_cast<u32>(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')));
+ .arg(error.raw, 8, 16, QChar::fromLatin1('0')),
+ tr("An error has occurred.\nPlease try again or contact the developer of the software."));
}
void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
@@ -32,13 +32,14 @@ void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::secon
const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count());
emit MainWindowDisplayError(
- 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")))
+ tr("Error Code: %1-%2 (0x%3)")
.arg(static_cast<u32>(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')));
+ .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"))));
}
void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text,
@@ -46,10 +47,11 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te
std::function<void()> finished) const {
callback = std::move(finished);
emit MainWindowDisplayError(
- tr("An error has occurred.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5")
+ tr("Error Code: %1-%2 (0x%3)")
.arg(static_cast<u32>(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'))
+ .arg(error.raw, 8, 16, QChar::fromLatin1('0')),
+ tr("An error has occurred.\n\n%1\n\n%2")
.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 b0932d895..8bd895a32 100644
--- a/src/yuzu/applets/error.h
+++ b/src/yuzu/applets/error.h
@@ -24,7 +24,7 @@ public:
std::function<void()> finished) const override;
signals:
- void MainWindowDisplayError(QString error) const;
+ void MainWindowDisplayError(QString error_code, QString error_text) const;
private:
void MainWindowFinishedError();
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp
index ab8cfd8ee..fd3368479 100644
--- a/src/yuzu/applets/software_keyboard.cpp
+++ b/src/yuzu/applets/software_keyboard.cpp
@@ -1,153 +1,1641 @@
-// Copyright 2018 yuzu Emulator Project
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <algorithm>
-#include <mutex>
-#include <QDialogButtonBox>
-#include <QFont>
-#include <QLabel>
-#include <QLineEdit>
-#include <QVBoxLayout>
-#include "core/hle/lock.h"
+#include <QCursor>
+#include <QKeyEvent>
+#include <QScreen>
+
+#include "common/logging/log.h"
+#include "common/settings.h"
+#include "common/string_util.h"
+#include "core/core.h"
+#include "core/frontend/input_interpreter.h"
+#include "ui_software_keyboard.h"
#include "yuzu/applets/software_keyboard.h"
#include "yuzu/main.h"
+#include "yuzu/util/overlay_dialog.h"
+
+namespace {
+
+using namespace Service::AM::Applets;
+
+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;
+
+} // Anonymous namespace
+
+QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
+ QWidget* parent, Core::System& system_, bool is_inline_,
+ Core::Frontend::KeyboardInitializeParameters initialize_parameters_)
+ : QDialog(parent), ui{std::make_unique<Ui::QtSoftwareKeyboardDialog>()}, system{system_},
+ is_inline{is_inline_}, initialize_parameters{std::move(initialize_parameters_)} {
+ ui->setupUi(this);
+
+ setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint |
+ Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint);
+ setWindowModality(Qt::WindowModal);
+ setAttribute(Qt::WA_DeleteOnClose);
+ setAttribute(Qt::WA_TranslucentBackground);
+
+ 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,
+ },
+ }},
+ }};
-QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator(
- Core::Frontend::SoftwareKeyboardParameters parameters)
- : parameters(std::move(parameters)) {}
+ 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,
+ },
+ }};
-QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const {
- if (input.size() > static_cast<s64>(parameters.max_length)) {
- return Invalid;
+ 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,
+ };
+
+ SetupMouseHover();
+
+ if (!initialize_parameters.ok_text.empty()) {
+ ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text));
}
- if (parameters.disable_space && input.contains(QLatin1Char{' '})) {
- return Invalid;
+
+ 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);
+ }
+ });
}
- if (parameters.disable_address && input.contains(QLatin1Char{'@'})) {
- return Invalid;
+
+ // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
+ if (system.IsPoweredOn()) {
+ input_interpreter = std::make_unique<InputInterpreter>(system);
}
- if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) {
- return Invalid;
+}
+
+QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() {
+ StopInputThread();
+}
+
+void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) {
+ if (isVisible()) {
+ return;
}
- if (parameters.disable_slash &&
- (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) {
- return Invalid;
+
+ 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;
}
- if (parameters.disable_number &&
- std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) {
- return Invalid;
+ 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;
- if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) {
- return c == QLatin1Char{'O'} || c == QLatin1Char{'I'};
- })) {
- return Invalid;
+ 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<int>(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::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);
}
+}
+
+void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) {
+ if (!is_inline) {
+ QDialog::keyPressEvent(event);
+ return;
+ }
+
+ const auto entered_key = event->key();
- return Acceptable;
+ 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());
}
-QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
- QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_)
- : QDialog(parent), parameters(std::move(parameters_)) {
- layout = new QVBoxLayout;
-
- 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:"));
-
- 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());
-
- guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text));
- guide_label->setHidden(parameters.guide_text.empty());
-
- length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length));
- length_label->setAlignment(Qt::AlignRight);
- length_label->setFont({length_label->font().family(), 8});
-
- line_edit = new QLineEdit;
- line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters));
- line_edit->setMaxLength(static_cast<int>(parameters.max_length));
- line_edit->setText(QString::fromStdU16String(parameters.initial_text));
- line_edit->setCursorPosition(
- parameters.cursor_at_beginning ? 0 : static_cast<int>(parameters.initial_text.size()));
- line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal);
-
- 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);
+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<int>(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<int>(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<u32>(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<u32>(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<u32>(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 {
- buttons->addButton(QString::fromStdU16String(parameters.submit_text),
- QDialogButtonBox::AcceptRole);
+ const auto text_length = [this] {
+ if (ui->topOSK->currentIndex() == 1) {
+ return static_cast<u32>(ui->text_edit_osk->toPlainText().length());
+ } else {
+ return static_cast<u32>(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);
}
- 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() = default;
+bool QtSoftwareKeyboardDialog::ValidateInputText(const QString& input_text) {
+ const auto& key_disable_flags = initialize_parameters.key_disable_flags;
+
+ const auto input_text_length = static_cast<u32>(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;
+ }
-void QtSoftwareKeyboardDialog::accept() {
- text = line_edit->text().toStdU16String();
- QDialog::accept();
+ 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::reject() {
- text.clear();
- QDialog::reject();
+void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() {
+ switch (bottom_osk_index) {
+ case BottomOSKIndex::LowerCase:
+ bottom_osk_index = BottomOSKIndex::UpperCase;
+ ui->bottomOSK->setCurrentIndex(static_cast<int>(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<int>(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;
+ }
}
-std::u16string QtSoftwareKeyboardDialog::GetText() const {
- return text;
+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<s32>(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 <HIDButton... T>
+void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() {
+ const auto f = [this](HIDButton button) {
+ if (input_interpreter->IsButtonPressedOnce(button)) {
+ TranslateButtonPress(button);
+ }
+ };
+
+ (f(T), ...);
+}
+
+template <HIDButton... T>
+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<std::size_t>(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<std::size_t>(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<s32>(current_text.size())) {
+ cursor_position = static_cast<s32>(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<HIDButton::A, HIDButton::B, HIDButton::X, HIDButton::Y,
+ HIDButton::LStick, HIDButton::RStick, HIDButton::L, HIDButton::R,
+ HIDButton::Plus, HIDButton::DLeft, HIDButton::DUp,
+ HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft,
+ HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown,
+ HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight,
+ HIDButton::RStickDown>();
+
+ HandleButtonHold<HIDButton::B, HIDButton::L, HIDButton::R, HIDButton::DLeft, HIDButton::DUp,
+ HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft,
+ HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown,
+ HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight,
+ HIDButton::RStickDown>();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
}
QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) {
- 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);
+ 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);
}
QtSoftwareKeyboard::~QtSoftwareKeyboard() = default;
-void QtSoftwareKeyboard::RequestText(std::function<void(std::optional<std::u16string>)> out,
- Core::Frontend::SoftwareKeyboardParameters parameters) const {
- text_output = std::move(out);
- emit MainWindowGetText(parameters);
+void QtSoftwareKeyboard::InitializeKeyboard(
+ bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
+ std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_,
+ std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ 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::ShowNormalKeyboard() const {
+ emit MainWindowShowNormalKeyboard();
+}
+
+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::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::SendTextCheckDialog(std::u16string error_message,
- std::function<void()> finished_check_) const {
- finished_check = std::move(finished_check_);
- emit MainWindowTextCheckDialog(error_message);
+void QtSoftwareKeyboard::ExitKeyboard() const {
+ emit MainWindowExitKeyboard();
}
-void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) {
- // Acquire the HLE mutex
- std::lock_guard lock{HLE::g_hle_lock};
- text_output(std::move(text));
+void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result,
+ std::u16string submitted_text) const {
+ submit_normal_callback(result, submitted_text);
}
-void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() {
- // Acquire the HLE mutex
- std::lock_guard lock{HLE::g_hle_lock};
- finished_check();
+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);
}
diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h
index 9e1094cce..1a03c098c 100644
--- a/src/yuzu/applets/software_keyboard.h
+++ b/src/yuzu/applets/software_keyboard.h
@@ -1,54 +1,228 @@
-// Copyright 2018 yuzu Emulator Project
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
+#include <array>
+#include <atomic>
+#include <memory>
+#include <thread>
+
#include <QDialog>
#include <QValidator>
+
#include "core/frontend/applets/software_keyboard.h"
-class GMainWindow;
-class QDialogButtonBox;
-class QLabel;
-class QLineEdit;
-class QVBoxLayout;
-class QtSoftwareKeyboard;
+enum class HIDButton : u8;
-class QtSoftwareKeyboardValidator final : public QValidator {
-public:
- explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters);
- State validate(QString& input, int& pos) const override;
+class InputInterpreter;
-private:
- Core::Frontend::SoftwareKeyboardParameters parameters;
-};
+namespace Core {
+class System;
+}
+
+namespace Ui {
+class QtSoftwareKeyboardDialog;
+}
+
+class GMainWindow;
class QtSoftwareKeyboardDialog final : public QDialog {
Q_OBJECT
public:
- QtSoftwareKeyboardDialog(QWidget* parent,
- Core::Frontend::SoftwareKeyboardParameters parameters);
+ QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_,
+ Core::Frontend::KeyboardInitializeParameters initialize_parameters_);
~QtSoftwareKeyboardDialog() override;
- void accept() 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 reject() override;
- std::u16string GetText() const;
+protected:
+ /// We override the keyPressEvent for inputting text into the inline software keyboard.
+ void keyPressEvent(QKeyEvent* event) override;
private:
- std::u16string text;
+ enum class Direction {
+ Left,
+ Up,
+ Right,
+ Down,
+ };
+
+ enum class BottomOSKIndex {
+ LowerCase,
+ UpperCase,
+ NumberPad,
+ };
+
+ /**
+ * 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);
- QDialogButtonBox* buttons;
- QLabel* header_label;
- QLabel* sub_label;
- QLabel* guide_label;
- QLabel* length_label;
- QLineEdit* line_edit;
- QVBoxLayout* layout;
+ /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once.
+ void SetupMouseHover();
- Core::Frontend::SoftwareKeyboardParameters parameters;
+ /**
+ * Handles button presses and converts them into keyboard input.
+ *
+ * @tparam HIDButton The list of buttons that can be converted into keyboard input.
+ */
+ template <HIDButton... T>
+ 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 <HIDButton... T>
+ 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::QtSoftwareKeyboardDialog> 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<std::array<std::array<QPushButton*, NUM_COLUMNS_NORMAL>, NUM_ROWS_NORMAL>, 2>
+ keyboard_buttons;
+ // Stores the numberpad keyboard layout.
+ std::array<std::array<QPushButton*, NUM_COLUMNS_NUMPAD>, NUM_ROWS_NUMPAD> numberpad_buttons;
+
+ // Contains a set of all buttons used in keyboard_buttons and numberpad_buttons.
+ std::array<QPushButton*, 110> all_buttons;
+
+ std::size_t row{0};
+ std::size_t column{0};
+
+ BottomOSKIndex bottom_osk_index{BottomOSKIndex::LowerCase};
+ std::atomic<bool> caps_lock_enabled{false};
+
+ std::unique_ptr<InputInterpreter> input_interpreter;
+
+ std::thread input_thread;
+
+ std::atomic<bool> input_thread_running{};
};
class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet {
@@ -58,19 +232,54 @@ public:
explicit QtSoftwareKeyboard(GMainWindow& parent);
~QtSoftwareKeyboard() override;
- void RequestText(std::function<void(std::optional<std::u16string>)> out,
- Core::Frontend::SoftwareKeyboardParameters parameters) const override;
- void SendTextCheckDialog(std::u16string error_message,
- std::function<void()> finished_check_) const override;
+ void InitializeKeyboard(
+ bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
+ std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
+ submit_normal_callback_,
+ std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ 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;
signals:
- void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const;
- void MainWindowTextCheckDialog(std::u16string error_message) const;
+ 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;
private:
- void MainWindowFinishedText(std::optional<std::u16string> text);
- void MainWindowFinishedCheckDialog();
+ 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;
- mutable std::function<void(std::optional<std::u16string>)> text_output;
- mutable std::function<void()> finished_check;
+ mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
+ submit_normal_callback;
+ mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ submit_inline_callback;
};
diff --git a/src/yuzu/applets/software_keyboard.ui b/src/yuzu/applets/software_keyboard.ui
new file mode 100644
index 000000000..b0a1fcde9
--- /dev/null
+++ b/src/yuzu/applets/software_keyboard.ui
@@ -0,0 +1,3503 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QtSoftwareKeyboardDialog</class>
+ <widget class="QDialog" name="QtSoftwareKeyboardDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1280</width>
+ <height>720</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Software Keyboard</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QWidget" name="mainOSK" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_2" stretch="320,400">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="topOSK">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="lineOSK">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>100</height>
+ </size>
+ </property>
+ <layout class="QVBoxLayout" name="lineOSKVerticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="gridLineOSK" rowstretch="40,50,23,48,65,94" columnstretch="130,1020,130">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="4" column="2">
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="0">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="5" column="1">
+ <widget class="QWidget" name="charactersOSK" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item alignment="Qt::AlignRight|Qt::AlignTop">
+ <widget class="QLabel" name="label_characters">
+ <property name="font">
+ <font>
+ <pointsize>17</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">0/32</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="5" column="0">
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="1">
+ <widget class="QWidget" name="inputOSK" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QLineEdit" name="line_edit_osk">
+ <property name="font">
+ <font>
+ <pointsize>26</pointsize>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="maxLength">
+ <number>32</number>
+ </property>
+ <property name="placeholderText">
+ <string>Enter Text</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" colspan="3">
+ <widget class="QWidget" name="headerOSK" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="130,1020,130">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer_18">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>127</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_header">
+ <property name="font">
+ <font>
+ <pointsize>23</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_19">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>127</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="3">
+ <widget class="QWidget" name="subOSK" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="130,1020,130">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer_16">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>127</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_sub">
+ <property name="font">
+ <font>
+ <pointsize>17</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_17">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>127</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="boxOSK">
+ <layout class="QVBoxLayout" name="boxOSKVerticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="gridBoxOSK" rowstretch="61,178,81" columnstretch="120,1040,120">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_20">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="2">
+ <spacer name="horizontalSpacer_21">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" alignment="Qt::AlignRight|Qt::AlignTop">
+ <widget class="QWidget" name="charactersBoxOSK" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_characters_box">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>17</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">0/500</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QWidget" name="inputBoxOSK" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>14</number>
+ </property>
+ <property name="topMargin">
+ <number>9</number>
+ </property>
+ <property name="rightMargin">
+ <number>14</number>
+ </property>
+ <property name="bottomMargin">
+ <number>9</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="text_edit_osk">
+ <property name="font">
+ <font>
+ <pointsize>26</pointsize>
+ </font>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="html">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:26pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QStackedWidget" name="bottomOSK">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="normalOSK">
+ <layout class="QVBoxLayout" name="normalPageVerticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="kbOSKnormal" rowstretch="15,63,63,63,63,63,70" columnstretch="54,96,96,96,96,96,96,96,96,96,96,96,116,54">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="6" column="1" colspan="12">
+ <widget class="QWidget" name="legendOSK" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="70,525,25,12,22,41,25,12,22,41,25,12,47,37,29,12,69,37,29,12,56,8">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QWidget" name="icon_controller" native="true">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_L" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_14">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="arrow_left" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_13">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_R" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_12">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="arrow_right" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_11">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_press_stick" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_10">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_shift">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Shift</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_15">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_X" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_9">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_cancel">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_8">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_A" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_enter">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Enter</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="11">
+ <widget class="QPushButton" name="button_minus">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="11">
+ <widget class="QPushButton" name="button_apostrophe">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">'</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="11">
+ <widget class="QPushButton" name="button_slash">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">/</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="11">
+ <widget class="QPushButton" name="button_exclamation">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">!</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="7">
+ <widget class="QPushButton" name="button_7">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">7</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="8">
+ <widget class="QPushButton" name="button_8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">8</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="10">
+ <widget class="QPushButton" name="button_0">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="9">
+ <widget class="QPushButton" name="button_9">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">9</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="button_w">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">w</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="4">
+ <widget class="QPushButton" name="button_r">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">r</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QPushButton" name="button_e">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">e</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="button_q">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">q</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="7">
+ <widget class="QPushButton" name="button_u">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">u</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="6">
+ <widget class="QPushButton" name="button_y">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">y</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5">
+ <widget class="QPushButton" name="button_t">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">t</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="9">
+ <widget class="QPushButton" name="button_o">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">o</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="10">
+ <widget class="QPushButton" name="button_p">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">p</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="8">
+ <widget class="QPushButton" name="button_i">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">i</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QPushButton" name="button_a">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">a</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QPushButton" name="button_s">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">s</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="3">
+ <widget class="QPushButton" name="button_d">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">d</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="4">
+ <widget class="QPushButton" name="button_f">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">f</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="6">
+ <widget class="QPushButton" name="button_h">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">h</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="7">
+ <widget class="QPushButton" name="button_j">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">j</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="5">
+ <widget class="QPushButton" name="button_g">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">g</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="8">
+ <widget class="QPushButton" name="button_k">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">k</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="9">
+ <widget class="QPushButton" name="button_l">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">l</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="10">
+ <widget class="QPushButton" name="button_colon">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="12" rowspan="2">
+ <widget class="QPushButton" name="button_return">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Return</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="12" rowspan="2">
+ <widget class="QPushButton" name="button_ok">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">OK</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QPushButton" name="button_z">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">z</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3">
+ <widget class="QPushButton" name="button_c">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">c</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QPushButton" name="button_x">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">x</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="4">
+ <widget class="QPushButton" name="button_v">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">v</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="7">
+ <widget class="QPushButton" name="button_m">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="8">
+ <widget class="QPushButton" name="button_comma">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">,</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="6">
+ <widget class="QPushButton" name="button_n">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">n</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="5">
+ <widget class="QPushButton" name="button_b">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">b</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2">
+ <widget class="QPushButton" name="button_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="10">
+ <widget class="QPushButton" name="button_question">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">?</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="9">
+ <widget class="QPushButton" name="button_dot">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="button_1">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QPushButton" name="button_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">3</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QPushButton" name="button_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">4</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="button_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">2</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="6">
+ <widget class="QPushButton" name="button_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">6</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5">
+ <widget class="QPushButton" name="button_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">5</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="3" colspan="9">
+ <widget class="QPushButton" name="button_space">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Space</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="12">
+ <widget class="QPushButton" name="button_backspace">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="13">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="shiftOSK">
+ <layout class="QVBoxLayout" name="shiftPageVerticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="kbOSKshift" rowstretch="15,63,63,63,63,63,70" columnstretch="54,96,96,96,96,96,96,96,96,96,96,96,116,54">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="6" column="1" colspan="12">
+ <widget class="QWidget" name="legendOSKshift" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="70,464,25,12,22,41,25,12,22,41,25,12,95,37,29,12,69,37,29,12,56,8">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QWidget" name="icon_controller_shift" native="true">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_22">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_L_shift" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_23">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="arrow_left_shift" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_24">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_R_shift" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_25">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="arrow_right_shift" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_26">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_press_stick_shift" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_27">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_shift_shift">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Caps Lock</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_28">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_X_shift" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_29">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_cancel_shift">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_30">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_A_shift" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_31">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_enter_shift">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Enter</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_32">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="11">
+ <widget class="QPushButton" name="button_underscore">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">_</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="11">
+ <widget class="QPushButton" name="button_quotation">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">&quot;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="11">
+ <widget class="QPushButton" name="button_at">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">@</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="11">
+ <widget class="QPushButton" name="button_equal">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">=</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="7">
+ <widget class="QPushButton" name="button_ampersand">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">&amp;&amp;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="8">
+ <widget class="QPushButton" name="button_asterisk">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">*</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="10">
+ <widget class="QPushButton" name="button_right_parenthesis">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="9">
+ <widget class="QPushButton" name="button_left_parenthesis">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">(</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="button_w_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">W</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="4">
+ <widget class="QPushButton" name="button_r_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">R</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QPushButton" name="button_e_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">E</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="button_q_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Q</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="7">
+ <widget class="QPushButton" name="button_u_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">U</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="6">
+ <widget class="QPushButton" name="button_y_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Y</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5">
+ <widget class="QPushButton" name="button_t_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">T</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="9">
+ <widget class="QPushButton" name="button_o_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">O</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="10">
+ <widget class="QPushButton" name="button_p_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">P</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="8">
+ <widget class="QPushButton" name="button_i_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">I</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QPushButton" name="button_a_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">A</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QPushButton" name="button_s_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">S</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="3">
+ <widget class="QPushButton" name="button_d_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">D</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="4">
+ <widget class="QPushButton" name="button_f_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">F</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="6">
+ <widget class="QPushButton" name="button_h_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">H</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="7">
+ <widget class="QPushButton" name="button_j_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">J</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="5">
+ <widget class="QPushButton" name="button_g_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">G</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="8">
+ <widget class="QPushButton" name="button_k_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">K</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="9">
+ <widget class="QPushButton" name="button_l_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">L</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="10">
+ <widget class="QPushButton" name="button_semicolon">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="12" rowspan="2">
+ <widget class="QPushButton" name="button_return_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Return</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="12" rowspan="2">
+ <widget class="QPushButton" name="button_ok_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">OK</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QPushButton" name="button_z_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Z</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3">
+ <widget class="QPushButton" name="button_c_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">C</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QPushButton" name="button_x_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">X</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="4">
+ <widget class="QPushButton" name="button_v_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">V</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="7">
+ <widget class="QPushButton" name="button_m_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">M</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="8">
+ <widget class="QPushButton" name="button_less_than">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">&lt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="6">
+ <widget class="QPushButton" name="button_n_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">N</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="5">
+ <widget class="QPushButton" name="button_b_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">B</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2">
+ <widget class="QPushButton" name="button_shift_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="10">
+ <widget class="QPushButton" name="button_plus">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">+</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="9">
+ <widget class="QPushButton" name="button_greater_than">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="button_hash">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">#</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QPushButton" name="button_right_bracket">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QPushButton" name="button_dollar">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">$</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="button_left_bracket">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">[</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="6">
+ <widget class="QPushButton" name="button_circumflex">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">^</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5">
+ <widget class="QPushButton" name="button_percent">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">%</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="3" colspan="9">
+ <widget class="QPushButton" name="button_space_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Space</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="12">
+ <widget class="QPushButton" name="button_backspace_shift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_33">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="13">
+ <spacer name="horizontalSpacer_34">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="numOSK">
+ <layout class="QVBoxLayout" name="graphicsTabVerticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="kbOSKnum" rowstretch="18,63,63,63,63,10,70" columnstretch="54,307,186,186,186,120,187,54">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="1" column="5">
+ <widget class="QPushButton" name="button_backspace_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="6">
+ <spacer name="horizontalSpacer_35">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <spacer name="horizontalSpacer_36">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="2">
+ <spacer name="verticalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="6" column="1" colspan="6">
+ <widget class="QWidget" name="legendOSKnum" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="25,70,601,25,12,22,41,25,12,22,41,29,12,69,37,29,12,56,30">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer_48">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="icon_controller_num" native="true">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_38">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_L_num" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_39">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="arrow_left_num" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_40">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_R_num" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_41">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="arrow_right_num" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_42">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_X_num" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_43">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_cancel_num">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_44">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="button_A_num" native="true"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_45">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_enter_num">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">Enter</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_46">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="4">
+ <widget class="QPushButton" name="button_6_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">6</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="button_4_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">4</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="4">
+ <widget class="QPushButton" name="button_9_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">9</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QPushButton" name="button_5_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">5</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5" rowspan="3">
+ <widget class="QPushButton" name="button_ok_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">OK</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QPushButton" name="button_7_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">7</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="3">
+ <widget class="QPushButton" name="button_8_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">8</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QPushButton" name="button_2_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">2</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="button_1_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3">
+ <widget class="QPushButton" name="button_0_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QPushButton" name="button_3_num">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>28</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string notr="true">3</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_37">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="7">
+ <spacer name="horizontalSpacer_47">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="5" column="3">
+ <spacer name="verticalSpacer_8">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>button_1</tabstop>
+ <tabstop>button_2</tabstop>
+ <tabstop>button_3</tabstop>
+ <tabstop>button_4</tabstop>
+ <tabstop>button_5</tabstop>
+ <tabstop>button_6</tabstop>
+ <tabstop>button_7</tabstop>
+ <tabstop>button_8</tabstop>
+ <tabstop>button_9</tabstop>
+ <tabstop>button_0</tabstop>
+ <tabstop>button_minus</tabstop>
+ <tabstop>button_backspace</tabstop>
+ <tabstop>button_q</tabstop>
+ <tabstop>button_w</tabstop>
+ <tabstop>button_e</tabstop>
+ <tabstop>button_r</tabstop>
+ <tabstop>button_t</tabstop>
+ <tabstop>button_y</tabstop>
+ <tabstop>button_u</tabstop>
+ <tabstop>button_i</tabstop>
+ <tabstop>button_o</tabstop>
+ <tabstop>button_p</tabstop>
+ <tabstop>button_slash</tabstop>
+ <tabstop>button_return</tabstop>
+ <tabstop>button_a</tabstop>
+ <tabstop>button_s</tabstop>
+ <tabstop>button_d</tabstop>
+ <tabstop>button_f</tabstop>
+ <tabstop>button_g</tabstop>
+ <tabstop>button_h</tabstop>
+ <tabstop>button_j</tabstop>
+ <tabstop>button_k</tabstop>
+ <tabstop>button_l</tabstop>
+ <tabstop>button_colon</tabstop>
+ <tabstop>button_apostrophe</tabstop>
+ <tabstop>button_z</tabstop>
+ <tabstop>button_x</tabstop>
+ <tabstop>button_c</tabstop>
+ <tabstop>button_v</tabstop>
+ <tabstop>button_b</tabstop>
+ <tabstop>button_n</tabstop>
+ <tabstop>button_m</tabstop>
+ <tabstop>button_comma</tabstop>
+ <tabstop>button_dot</tabstop>
+ <tabstop>button_question</tabstop>
+ <tabstop>button_exclamation</tabstop>
+ <tabstop>button_ok</tabstop>
+ <tabstop>button_shift</tabstop>
+ <tabstop>button_space</tabstop>
+ <tabstop>button_hash</tabstop>
+ <tabstop>button_left_bracket</tabstop>
+ <tabstop>button_right_bracket</tabstop>
+ <tabstop>button_dollar</tabstop>
+ <tabstop>button_percent</tabstop>
+ <tabstop>button_circumflex</tabstop>
+ <tabstop>button_ampersand</tabstop>
+ <tabstop>button_asterisk</tabstop>
+ <tabstop>button_left_parenthesis</tabstop>
+ <tabstop>button_right_parenthesis</tabstop>
+ <tabstop>button_underscore</tabstop>
+ <tabstop>button_backspace_shift</tabstop>
+ <tabstop>button_q_shift</tabstop>
+ <tabstop>button_w_shift</tabstop>
+ <tabstop>button_e_shift</tabstop>
+ <tabstop>button_r_shift</tabstop>
+ <tabstop>button_t_shift</tabstop>
+ <tabstop>button_y_shift</tabstop>
+ <tabstop>button_u_shift</tabstop>
+ <tabstop>button_i_shift</tabstop>
+ <tabstop>button_o_shift</tabstop>
+ <tabstop>button_p_shift</tabstop>
+ <tabstop>button_at</tabstop>
+ <tabstop>button_return_shift</tabstop>
+ <tabstop>button_a_shift</tabstop>
+ <tabstop>button_s_shift</tabstop>
+ <tabstop>button_d_shift</tabstop>
+ <tabstop>button_f_shift</tabstop>
+ <tabstop>button_g_shift</tabstop>
+ <tabstop>button_h_shift</tabstop>
+ <tabstop>button_j_shift</tabstop>
+ <tabstop>button_k_shift</tabstop>
+ <tabstop>button_l_shift</tabstop>
+ <tabstop>button_semicolon</tabstop>
+ <tabstop>button_quotation</tabstop>
+ <tabstop>button_z_shift</tabstop>
+ <tabstop>button_x_shift</tabstop>
+ <tabstop>button_c_shift</tabstop>
+ <tabstop>button_v_shift</tabstop>
+ <tabstop>button_b_shift</tabstop>
+ <tabstop>button_n_shift</tabstop>
+ <tabstop>button_m_shift</tabstop>
+ <tabstop>button_less_than</tabstop>
+ <tabstop>button_greater_than</tabstop>
+ <tabstop>button_plus</tabstop>
+ <tabstop>button_equal</tabstop>
+ <tabstop>button_ok_shift</tabstop>
+ <tabstop>button_shift_shift</tabstop>
+ <tabstop>button_space_shift</tabstop>
+ <tabstop>button_1_num</tabstop>
+ <tabstop>button_2_num</tabstop>
+ <tabstop>button_3_num</tabstop>
+ <tabstop>button_backspace_num</tabstop>
+ <tabstop>button_4_num</tabstop>
+ <tabstop>button_5_num</tabstop>
+ <tabstop>button_6_num</tabstop>
+ <tabstop>button_ok_num</tabstop>
+ <tabstop>button_7_num</tabstop>
+ <tabstop>button_8_num</tabstop>
+ <tabstop>button_9_num</tabstop>
+ <tabstop>button_0_num</tabstop>
+ </tabstops>
+ <resources>
+ <include location="../../../dist/icons/overlay/overlay.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 15c09e0ad..9c7daeac7 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -29,10 +29,10 @@
#include "common/microprofile.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/frontend/framebuffer_layout.h"
#include "core/hle/kernel/process.h"
-#include "core/settings.h"
#include "input_common/keyboard.h"
#include "input_common/main.h"
#include "input_common/mouse/mouse_input.h"
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index ff6a6e961..d1b8c4fc9 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -29,9 +29,10 @@ Config::~Config() {
}
const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
- Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q,
- Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T,
- Qt::Key_H, Qt::Key_G, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V,
+ Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F,
+ Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T,
+ Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right,
+ Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0,
};
const std::array<int, Settings::NativeMotion::NumMotions> Config::default_motions = {
@@ -41,10 +42,10 @@ const std::array<int, Settings::NativeMotion::NumMotions> Config::default_motion
const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{
{
- Qt::Key_Up,
- Qt::Key_Down,
- Qt::Key_Left,
- Qt::Key_Right,
+ Qt::Key_W,
+ Qt::Key_S,
+ Qt::Key_A,
+ Qt::Key_D,
},
{
Qt::Key_I,
@@ -55,8 +56,8 @@ const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> Config:
}};
const std::array<int, 2> Config::default_stick_mod = {
- Qt::Key_E,
- Qt::Key_R,
+ Qt::Key_Shift,
+ 0,
};
const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::default_mouse_buttons =
@@ -641,6 +642,8 @@ void Config::ReadDebuggingValues() {
ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool();
Settings::values.extended_logging =
ReadSetting(QStringLiteral("extended_logging"), false).toBool();
+ Settings::values.use_debug_asserts =
+ ReadSetting(QStringLiteral("use_debug_asserts"), false).toBool();
Settings::values.use_auto_stub = ReadSetting(QStringLiteral("use_auto_stub"), false).toBool();
qt_config->endGroup();
@@ -1245,6 +1248,7 @@ void Config::SaveDebuggingValues() {
WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false);
WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false);
WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false);
+ WriteSetting(QStringLiteral("use_debug_asserts"), Settings::values.use_debug_asserts, false);
WriteSetting(QStringLiteral("disable_macro_jit"), Settings::values.disable_macro_jit, false);
qt_config->endGroup();
@@ -1613,7 +1617,7 @@ void Config::Reload() {
ReadValues();
// To apply default value changes
SaveValues();
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
}
void Config::Save() {
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 949c4eb13..5a2c026b3 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -9,7 +9,7 @@
#include <string>
#include <QMetaType>
#include <QVariant>
-#include "core/settings.h"
+#include "common/settings.h"
#include "yuzu/uisettings.h"
class QSettings;
@@ -131,6 +131,6 @@ private:
bool global;
};
-// These metatype declarations cannot be in core/settings.h because core is devoid of QT
+// These metatype declarations cannot be in common/settings.h because core is devoid of QT
Q_DECLARE_METATYPE(Settings::RendererBackend);
Q_DECLARE_METATYPE(Settings::GPUAccuracy);
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index 18482795c..89be4a62d 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -6,7 +6,7 @@
#include <QComboBox>
#include <QObject>
#include <QString>
-#include "core/settings.h"
+#include "common/settings.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_per_game.h"
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index 312b9e549..5b344cdbd 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -7,7 +7,7 @@
#include <QCheckBox>
#include <QComboBox>
#include <QString>
-#include "core/settings.h"
+#include "common/settings.h"
namespace ConfigurationShared {
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index db9518798..f9507e228 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -8,8 +8,8 @@
#include "audio_core/sink.h"
#include "audio_core/sink_details.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_audio.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_audio.h"
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index d055cbd60..4f99bc80f 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -7,8 +7,8 @@
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_cpu.h"
#include "yuzu/configuration/configure_cpu.h"
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h
index 3c5683d81..ef77b2e7e 100644
--- a/src/yuzu/configuration/configure_cpu.h
+++ b/src/yuzu/configuration/configure_cpu.h
@@ -6,7 +6,7 @@
#include <memory>
#include <QWidget>
-#include "core/settings.h"
+#include "common/settings.h"
namespace Ui {
class ConfigureCpu;
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp
index 3385b2cf6..c925c023c 100644
--- a/src/yuzu/configuration/configure_cpu_debug.cpp
+++ b/src/yuzu/configuration/configure_cpu_debug.cpp
@@ -6,8 +6,8 @@
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_cpu_debug.h"
#include "yuzu/configuration/configure_cpu_debug.h"
diff --git a/src/yuzu/configuration/configure_cpu_debug.h b/src/yuzu/configuration/configure_cpu_debug.h
index c9941ef3b..10de55099 100644
--- a/src/yuzu/configuration/configure_cpu_debug.h
+++ b/src/yuzu/configuration/configure_cpu_debug.h
@@ -6,7 +6,7 @@
#include <memory>
#include <QWidget>
-#include "core/settings.h"
+#include "common/settings.h"
namespace Ui {
class ConfigureCpuDebug;
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index 2a5b3f5e7..6730eb356 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -7,8 +7,8 @@
#include "common/file_util.h"
#include "common/logging/backend.h"
#include "common/logging/filter.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_debug.h"
#include "yuzu/configuration/configure_debug.h"
#include "yuzu/debugger/console.h"
@@ -34,6 +34,7 @@ void ConfigureDebug::SetConfiguration() {
ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args));
ui->reporting_services->setChecked(Settings::values.reporting_services);
ui->quest_flag->setChecked(Settings::values.quest_flag);
+ ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts);
ui->use_auto_stub->setChecked(Settings::values.use_auto_stub);
ui->enable_graphics_debugging->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug);
@@ -48,14 +49,15 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
Settings::values.reporting_services = ui->reporting_services->isChecked();
Settings::values.quest_flag = ui->quest_flag->isChecked();
+ Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked();
Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
Settings::values.extended_logging = ui->extended_logging->isChecked();
Debugger::ToggleConsole();
- Log::Filter filter;
+ Common::Log::Filter filter;
filter.ParseFilterString(Settings::values.log_filter);
- Log::SetGlobalFilter(filter);
+ Common::Log::SetGlobalFilter(filter);
}
void ConfigureDebug::changeEvent(QEvent* event) {
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index ae48b728c..d812858b6 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -186,6 +186,13 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="use_debug_asserts">
+ <property name="text">
+ <string>Enable Debug Asserts</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QCheckBox" name="use_auto_stub">
<property name="text">
<string>Enable Auto-Stub</string>
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index d6b17a28d..3ad40d2b3 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -5,8 +5,8 @@
#include <QHash>
#include <QListWidgetItem>
#include <QSignalBlocker>
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure.h"
#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_dialog.h"
@@ -55,7 +55,7 @@ void ConfigureDialog::ApplyConfiguration() {
ui->debugTab->ApplyConfiguration();
ui->webTab->ApplyConfiguration();
ui->serviceTab->ApplyConfiguration();
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
Settings::LogSettings();
}
diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp
index 58f644af4..006eda4b0 100644
--- a/src/yuzu/configuration/configure_filesystem.cpp
+++ b/src/yuzu/configuration/configure_filesystem.cpp
@@ -6,7 +6,7 @@
#include <QMessageBox>
#include "common/common_paths.h"
#include "common/file_util.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "ui_configure_filesystem.h"
#include "yuzu/configuration/configure_filesystem.h"
#include "yuzu/uisettings.h"
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index d4d29d422..2fa88dcec 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -4,8 +4,8 @@
#include <QCheckBox>
#include <QSpinBox>
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_general.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_general.h"
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 8a2008b2a..0a7536617 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -11,8 +11,8 @@
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_graphics.h"
#include "video_core/vulkan_common/vulkan_instance.h"
#include "video_core/vulkan_common/vulkan_library.h"
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 1fefc88eb..c162048a2 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -8,7 +8,7 @@
#include <vector>
#include <QString>
#include <QWidget>
-#include "core/settings.h"
+#include "common/settings.h"
namespace ConfigurationShared {
enum class CheckState;
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 383c7bac8..c67609b0e 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -2,8 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_graphics_advanced.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics_advanced.h"
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp
index cbee51a5e..ed76fe18e 100644
--- a/src/yuzu/configuration/configure_hotkeys.cpp
+++ b/src/yuzu/configuration/configure_hotkeys.cpp
@@ -5,7 +5,7 @@
#include <QMenu>
#include <QMessageBox>
#include <QStandardItemModel>
-#include "core/settings.h"
+#include "common/settings.h"
#include "ui_configure_hotkeys.h"
#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_hotkeys.h"
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index a1a0eb676..d8d3b83dc 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -3,8 +3,8 @@
// Refer to the license.txt file included.
#include <QColorDialog>
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_input_advanced.h"
#include "yuzu/configuration/configure_input_advanced.h"
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index efe953fbc..c7d101682 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -14,7 +14,7 @@
#include <QWidget>
#include "common/param_package.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "ui_configure_input.h"
class QCheckBox;
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index 91c3343f1..51bb84eb6 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -7,8 +7,8 @@
#include <array>
#include <QFrame>
#include <QPointer>
+#include "common/settings.h"
#include "core/frontend/input.h"
-#include "core/settings.h"
class QLabel;
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index 083d1ea43..6a5d625df 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -14,7 +14,7 @@
#include <QVBoxLayout>
#include "common/logging/log.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "input_common/main.h"
#include "input_common/udp/client.h"
#include "input_common/udp/udp.h"
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index f598513df..bd91ebc42 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -57,7 +57,7 @@ void ConfigurePerGame::ApplyConfiguration() {
ui->graphicsAdvancedTab->ApplyConfiguration();
ui->audioTab->ApplyConfiguration();
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
Settings::LogSettings();
game_config->Save();
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index 51647a028..d61b5e29b 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -13,10 +13,10 @@
#include <QVBoxLayout>
#include "common/assert.h"
#include "common/file_util.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/service/acc/profile_manager.h"
-#include "core/settings.h"
#include "ui_configure_profile_manager.h"
#include "yuzu/configuration/configure_profile_manager.h"
#include "yuzu/util/limitable_input_dialog.h"
@@ -180,7 +180,7 @@ void ConfigureProfileManager::ApplyConfiguration() {
return;
}
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
}
void ConfigureProfileManager::SelectUser(const QModelIndex& index) {
diff --git a/src/yuzu/configuration/configure_service.cpp b/src/yuzu/configuration/configure_service.cpp
index b580cfff2..6d954a67f 100644
--- a/src/yuzu/configuration/configure_service.cpp
+++ b/src/yuzu/configuration/configure_service.cpp
@@ -4,8 +4,8 @@
#include <QGraphicsItem>
#include <QtConcurrent/QtConcurrent>
+#include "common/settings.h"
#include "core/hle/service/bcat/backend/boxcat.h"
-#include "core/settings.h"
#include "ui_configure_service.h"
#include "yuzu/configuration/configure_service.h"
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 6cf2032da..268ed44c3 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -11,9 +11,9 @@
#include <QMessageBox>
#include "common/assert.h"
#include "common/file_util.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/hle/service/time/time.h"
-#include "core/settings.h"
#include "ui_configure_system.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_system.h"
@@ -199,7 +199,7 @@ void ConfigureSystem::ApplyConfiguration() {
}
}
- Settings::Apply(system);
+ system.ApplySettings();
}
void ConfigureSystem::RefreshConsoleID() {
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp
index 15557e4b8..40129f228 100644
--- a/src/yuzu/configuration/configure_touch_from_button.cpp
+++ b/src/yuzu/configuration/configure_touch_from_button.cpp
@@ -10,8 +10,8 @@
#include <QStandardItemModel>
#include <QTimer>
#include "common/param_package.h"
+#include "common/settings.h"
#include "core/frontend/framebuffer_layout.h"
-#include "core/settings.h"
#include "input_common/main.h"
#include "ui_configure_touch_from_button.h"
#include "yuzu/configuration/configure_touch_from_button.h"
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index aed876008..f35c89e04 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -9,8 +9,8 @@
#include <QDirIterator>
#include "common/common_types.h"
#include "common/file_util.h"
+#include "common/settings.h"
#include "core/core.h"
-#include "core/settings.h"
#include "ui_configure_ui.h"
#include "yuzu/configuration/configure_ui.h"
#include "yuzu/uisettings.h"
@@ -85,7 +85,7 @@ void ConfigureUi::ApplyConfiguration() {
UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked();
Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir,
ui->screenshot_path_edit->text().toStdString());
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
}
void ConfigureUi::RequestGameListUpdate() {
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index 7dcb2c5b9..9d92c4949 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -8,7 +8,7 @@
#include <fmt/format.h>
#include "common/param_package.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "ui_configure_vibration.h"
#include "yuzu/configuration/configure_vibration.h"
diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp
index 8637f5b3c..f3f3b54d6 100644
--- a/src/yuzu/configuration/configure_web.cpp
+++ b/src/yuzu/configuration/configure_web.cpp
@@ -5,7 +5,7 @@
#include <QIcon>
#include <QMessageBox>
#include <QtConcurrent/QtConcurrentRun>
-#include "core/settings.h"
+#include "common/settings.h"
#include "core/telemetry_session.h"
#include "ui_configure_web.h"
#include "yuzu/configuration/configure_web.h"
diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp
index 207ff4d58..c11a326ac 100644
--- a/src/yuzu/debugger/console.cpp
+++ b/src/yuzu/debugger/console.cpp
@@ -29,13 +29,13 @@ void ToggleConsole() {
freopen_s(&temp, "CONIN$", "r", stdin);
freopen_s(&temp, "CONOUT$", "w", stdout);
freopen_s(&temp, "CONOUT$", "w", stderr);
- Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
+ Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>());
}
} else {
if (FreeConsole()) {
// In order to close the console, we have to also detach the streams on it.
// Just redirect them to NUL if there is no console window
- Log::RemoveBackend(Log::ColorConsoleBackend::Name());
+ Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name());
freopen_s(&temp, "NUL", "r", stdin);
freopen_s(&temp, "NUL", "w", stdout);
freopen_s(&temp, "NUL", "w", stderr);
@@ -43,9 +43,9 @@ void ToggleConsole() {
}
#else
if (UISettings::values.show_console) {
- Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
+ Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>());
} else {
- Log::RemoveBackend(Log::ColorConsoleBackend::Name());
+ Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name());
}
#endif
}
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index 2731d948d..7186eac76 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -5,7 +5,7 @@
#include <QAction>
#include <QLayout>
#include <QString>
-#include "core/settings.h"
+#include "common/settings.h"
#include "yuzu/configuration/configure_input_player_widget.h"
#include "yuzu/debugger/controller.h"
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 23ea4983d..5f6cdc0c6 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -79,6 +79,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#ifdef ARCHITECTURE_x86_64
#include "common/x64/cpu_detect.h"
#endif
+#include "common/settings.h"
#include "common/telemetry.h"
#include "core/core.h"
#include "core/crypto/key_manager.h"
@@ -98,9 +99,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "core/hle/service/sm/sm.h"
#include "core/loader/loader.h"
#include "core/perf_stats.h"
-#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"
@@ -164,19 +165,21 @@ void GMainWindow::ShowTelemetryCallout() {
"<br/><br/>Would you like to share your usage data with us?");
if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) {
Settings::values.enable_telemetry = false;
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
}
}
const int GMainWindow::max_recent_files_item;
static void InitializeLogging() {
+ using namespace Common;
+
Log::Filter log_filter;
log_filter.ParseFilterString(Settings::values.log_filter);
Log::SetGlobalFilter(log_filter);
- const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir);
- Common::FS::CreateFullPath(log_dir);
+ const std::string& log_dir = FS::GetUserPath(FS::UserPath::LogDir);
+ FS::CreateFullPath(log_dir);
Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE));
#ifdef _WIN32
Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
@@ -225,6 +228,8 @@ GMainWindow::GMainWindow()
SetDiscordEnabled(UISettings::values.enable_discord_presence);
discord_rpc->Update();
+ RegisterMetaTypes();
+
InitializeWidgets();
InitializeDebugWidgets();
InitializeRecentFileMenuActions();
@@ -373,6 +378,55 @@ GMainWindow::~GMainWindow() {
delete render_window;
}
+void GMainWindow::RegisterMetaTypes() {
+ // Register integral and floating point types
+ qRegisterMetaType<u8>("u8");
+ qRegisterMetaType<u16>("u16");
+ qRegisterMetaType<u32>("u32");
+ qRegisterMetaType<u64>("u64");
+ qRegisterMetaType<u128>("u128");
+ qRegisterMetaType<s8>("s8");
+ qRegisterMetaType<s16>("s16");
+ qRegisterMetaType<s32>("s32");
+ qRegisterMetaType<s64>("s64");
+ qRegisterMetaType<f32>("f32");
+ qRegisterMetaType<f64>("f64");
+
+ // Register string types
+ qRegisterMetaType<std::string>("std::string");
+ qRegisterMetaType<std::wstring>("std::wstring");
+ qRegisterMetaType<std::u8string>("std::u8string");
+ qRegisterMetaType<std::u16string>("std::u16string");
+ qRegisterMetaType<std::u32string>("std::u32string");
+ qRegisterMetaType<std::string_view>("std::string_view");
+ qRegisterMetaType<std::wstring_view>("std::wstring_view");
+ qRegisterMetaType<std::u8string_view>("std::u8string_view");
+ qRegisterMetaType<std::u16string_view>("std::u16string_view");
+ qRegisterMetaType<std::u32string_view>("std::u32string_view");
+
+ // Register applet types
+
+ // Controller Applet
+ qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
+
+ // Software Keyboard Applet
+ qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>(
+ "Core::Frontend::KeyboardInitializeParameters");
+ qRegisterMetaType<Core::Frontend::InlineAppearParameters>(
+ "Core::Frontend::InlineAppearParameters");
+ qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters");
+ qRegisterMetaType<Service::AM::Applets::SwkbdResult>("Service::AM::Applets::SwkbdResult");
+ qRegisterMetaType<Service::AM::Applets::SwkbdTextCheckResult>(
+ "Service::AM::Applets::SwkbdTextCheckResult");
+ qRegisterMetaType<Service::AM::Applets::SwkbdReplyType>("Service::AM::Applets::SwkbdReplyType");
+
+ // Web Browser Applet
+ qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason");
+
+ // Register loader types
+ qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
+}
+
void GMainWindow::ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters) {
QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get());
@@ -385,7 +439,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers(
emit ControllerSelectorReconfigureFinished();
// Don't forget to apply settings.
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
config->Save();
UpdateStatusButtons();
@@ -412,25 +466,112 @@ void GMainWindow::ProfileSelectorSelectProfile() {
emit ProfileSelectorFinishedSelection(uuid);
}
-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);
+void GMainWindow::SoftwareKeyboardInitialize(
+ bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) {
+ if (software_keyboard) {
+ LOG_ERROR(Frontend, "The software keyboard is already initialized!");
+ return;
+ }
- if (dialog.exec() == QDialog::Rejected) {
- emit SoftwareKeyboardFinishedText(std::nullopt);
+ 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);
+ }
+}
+
+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<int>(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<int>(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<int>(layout.screen.GetWidth() * appear_parameters.key_top_scale_x);
+ const auto h = static_cast<int>(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;
}
- emit SoftwareKeyboardFinishedText(dialog.GetText());
+ software_keyboard->HideInlineKeyboard();
}
-void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) {
- QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message));
- emit SoftwareKeyboardFinishedCheckDialog();
+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::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
@@ -650,7 +791,7 @@ void GMainWindow::InitializeWidgets() {
Settings::values.use_asynchronous_gpu_emulation.SetValue(
!Settings::values.use_asynchronous_gpu_emulation.GetValue());
async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue());
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
});
async_status_button->setText(tr("ASYNC"));
async_status_button->setCheckable(true);
@@ -666,7 +807,7 @@ void GMainWindow::InitializeWidgets() {
}
Settings::values.use_multi_core.SetValue(!Settings::values.use_multi_core.GetValue());
multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue());
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
});
multicore_status_button->setText(tr("MULTICORE"));
multicore_status_button->setCheckable(true);
@@ -697,7 +838,7 @@ void GMainWindow::InitializeWidgets() {
Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL);
}
- Settings::Apply(Core::System::GetInstance());
+ Core::System::GetInstance().ApplySettings();
});
statusBar()->insertPermanentWidget(0, renderer_status_button);
@@ -976,6 +1117,10 @@ 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);
}
@@ -2185,15 +2330,6 @@ void GMainWindow::OnStartGame() {
emu_thread->SetRunning(true);
- qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
- qRegisterMetaType<Core::Frontend::SoftwareKeyboardParameters>(
- "Core::Frontend::SoftwareKeyboardParameters");
- qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
- qRegisterMetaType<std::string>("std::string");
- qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>");
- qRegisterMetaType<std::string_view>("std::string_view");
- qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason");
-
connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
ui.action_Start->setEnabled(false);
@@ -2242,8 +2378,11 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
BootGame(last_filename_booted, program_index);
}
-void GMainWindow::ErrorDisplayDisplayError(QString body) {
- QMessageBox::critical(this, tr("Error Display"), body);
+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();
+
emit ErrorDisplayFinished();
}
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 04d37d4ae..7f1e50a5b 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -37,9 +37,13 @@ enum class GameListRemoveTarget;
enum class InstalledEntryType;
class GameListPlaceholder;
+class QtSoftwareKeyboardDialog;
+
namespace Core::Frontend {
struct ControllerParameters;
-struct SoftwareKeyboardParameters;
+struct InlineAppearParameters;
+struct InlineTextParameters;
+struct KeyboardInitializeParameters;
} // namespace Core::Frontend
namespace DiscordRPC {
@@ -57,8 +61,11 @@ 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,
@@ -128,8 +135,10 @@ signals:
void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid);
- void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
- void SoftwareKeyboardFinishedCheckDialog();
+ 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 WebBrowserExtractOfflineRomFS();
void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url);
@@ -139,15 +148,24 @@ public slots:
void OnExecuteProgram(std::size_t program_index);
void ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters);
- void ErrorDisplayDisplayError(QString body);
+ 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 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();
@@ -334,6 +352,9 @@ 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;
diff --git a/src/yuzu/util/overlay_dialog.cpp b/src/yuzu/util/overlay_dialog.cpp
new file mode 100644
index 000000000..95b148545
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.cpp
@@ -0,0 +1,249 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <QKeyEvent>
+#include <QScreen>
+
+#include "core/core.h"
+#include "core/frontend/input_interpreter.h"
+#include "ui_overlay_dialog.h"
+#include "yuzu/util/overlay_dialog.h"
+
+namespace {
+
+constexpr float BASE_TITLE_FONT_SIZE = 14.0f;
+constexpr float BASE_FONT_SIZE = 18.0f;
+constexpr float BASE_WIDTH = 1280.0f;
+constexpr float BASE_HEIGHT = 720.0f;
+
+} // Anonymous namespace
+
+OverlayDialog::OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text,
+ const QString& body_text, const QString& left_button_text,
+ const QString& right_button_text, Qt::Alignment alignment,
+ bool use_rich_text_)
+ : QDialog(parent), ui{std::make_unique<Ui::OverlayDialog>()}, use_rich_text{use_rich_text_} {
+ ui->setupUi(this);
+
+ setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint |
+ Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint);
+ setWindowModality(Qt::WindowModal);
+ setAttribute(Qt::WA_TranslucentBackground);
+
+ if (use_rich_text) {
+ InitializeRichTextDialog(title_text, body_text, left_button_text, right_button_text,
+ alignment);
+ } else {
+ InitializeRegularTextDialog(title_text, body_text, left_button_text, right_button_text,
+ alignment);
+ }
+
+ MoveAndResizeWindow();
+
+ // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
+ if (system.IsPoweredOn()) {
+ input_interpreter = std::make_unique<InputInterpreter>(system);
+
+ StartInputThread();
+ }
+}
+
+OverlayDialog::~OverlayDialog() {
+ StopInputThread();
+}
+
+void OverlayDialog::InitializeRegularTextDialog(const QString& title_text, const QString& body_text,
+ const QString& left_button_text,
+ const QString& right_button_text,
+ Qt::Alignment alignment) {
+ ui->stackedDialog->setCurrentIndex(0);
+
+ ui->label_title->setText(title_text);
+ ui->label_dialog->setText(body_text);
+ ui->button_cancel->setText(left_button_text);
+ ui->button_ok_label->setText(right_button_text);
+
+ ui->label_dialog->setAlignment(alignment);
+
+ if (title_text.isEmpty()) {
+ ui->label_title->hide();
+ ui->verticalLayout_2->setStretch(0, 0);
+ ui->verticalLayout_2->setStretch(1, 219);
+ ui->verticalLayout_2->setStretch(2, 82);
+ }
+
+ if (left_button_text.isEmpty()) {
+ ui->button_cancel->hide();
+ ui->button_cancel->setEnabled(false);
+ }
+
+ if (right_button_text.isEmpty()) {
+ ui->button_ok_label->hide();
+ ui->button_ok_label->setEnabled(false);
+ }
+
+ connect(
+ ui->button_cancel, &QPushButton::clicked, this,
+ [this](bool) {
+ StopInputThread();
+ QDialog::reject();
+ },
+ Qt::QueuedConnection);
+ connect(
+ ui->button_ok_label, &QPushButton::clicked, this,
+ [this](bool) {
+ StopInputThread();
+ QDialog::accept();
+ },
+ Qt::QueuedConnection);
+}
+
+void OverlayDialog::InitializeRichTextDialog(const QString& title_text, const QString& body_text,
+ const QString& left_button_text,
+ const QString& right_button_text,
+ Qt::Alignment alignment) {
+ ui->stackedDialog->setCurrentIndex(1);
+
+ ui->label_title_rich->setText(title_text);
+ ui->text_browser_dialog->setText(body_text);
+ ui->button_cancel_rich->setText(left_button_text);
+ ui->button_ok_rich->setText(right_button_text);
+
+ // TODO (Morph/Rei): Replace this with something that works better
+ ui->text_browser_dialog->setAlignment(alignment);
+
+ if (title_text.isEmpty()) {
+ ui->label_title_rich->hide();
+ ui->verticalLayout_3->setStretch(0, 0);
+ ui->verticalLayout_3->setStretch(1, 438);
+ ui->verticalLayout_3->setStretch(2, 82);
+ }
+
+ if (left_button_text.isEmpty()) {
+ ui->button_cancel_rich->hide();
+ ui->button_cancel_rich->setEnabled(false);
+ }
+
+ if (right_button_text.isEmpty()) {
+ ui->button_ok_rich->hide();
+ ui->button_ok_rich->setEnabled(false);
+ }
+
+ connect(
+ ui->button_cancel_rich, &QPushButton::clicked, this,
+ [this](bool) {
+ StopInputThread();
+ QDialog::reject();
+ },
+ Qt::QueuedConnection);
+ connect(
+ ui->button_ok_rich, &QPushButton::clicked, this,
+ [this](bool) {
+ StopInputThread();
+ QDialog::accept();
+ },
+ Qt::QueuedConnection);
+}
+
+void OverlayDialog::MoveAndResizeWindow() {
+ const auto pos = parentWidget()->mapToGlobal(parentWidget()->rect().topLeft());
+ const auto width = static_cast<float>(parentWidget()->width());
+ const auto height = static_cast<float>(parentWidget()->height());
+
+ // High DPI
+ const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f;
+
+ const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+ const auto body_text_font_size =
+ BASE_FONT_SIZE * (((width / BASE_WIDTH) + (height / BASE_HEIGHT)) / 2.0f) / dpi_scale;
+ const auto button_text_font_size = BASE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+
+ QFont title_text_font(QStringLiteral("MS Shell Dlg 2"), title_text_font_size, QFont::Normal);
+ QFont body_text_font(QStringLiteral("MS Shell Dlg 2"), body_text_font_size, QFont::Normal);
+ QFont button_text_font(QStringLiteral("MS Shell Dlg 2"), button_text_font_size, QFont::Normal);
+
+ if (use_rich_text) {
+ ui->label_title_rich->setFont(title_text_font);
+ ui->text_browser_dialog->setFont(body_text_font);
+ ui->button_cancel_rich->setFont(button_text_font);
+ ui->button_ok_rich->setFont(button_text_font);
+ } else {
+ ui->label_title->setFont(title_text_font);
+ ui->label_dialog->setFont(body_text_font);
+ ui->button_cancel->setFont(button_text_font);
+ ui->button_ok_label->setFont(button_text_font);
+ }
+
+ QDialog::move(pos);
+ QDialog::resize(width, height);
+}
+
+template <HIDButton... T>
+void OverlayDialog::HandleButtonPressedOnce() {
+ const auto f = [this](HIDButton button) {
+ if (input_interpreter->IsButtonPressedOnce(button)) {
+ TranslateButtonPress(button);
+ }
+ };
+
+ (f(T), ...);
+}
+
+void OverlayDialog::TranslateButtonPress(HIDButton button) {
+ QPushButton* left_button = use_rich_text ? ui->button_cancel_rich : ui->button_cancel;
+ QPushButton* right_button = use_rich_text ? ui->button_ok_rich : ui->button_ok_label;
+
+ // TODO (Morph): Handle QTextBrowser text scrolling
+ // TODO (Morph): focusPrevious/NextChild() doesn't work well with the rich text dialog, fix it
+
+ switch (button) {
+ case HIDButton::A:
+ case HIDButton::B:
+ if (left_button->hasFocus()) {
+ left_button->click();
+ } else if (right_button->hasFocus()) {
+ right_button->click();
+ }
+ break;
+ case HIDButton::DLeft:
+ case HIDButton::LStickLeft:
+ focusPreviousChild();
+ break;
+ case HIDButton::DRight:
+ case HIDButton::LStickRight:
+ focusNextChild();
+ break;
+ default:
+ break;
+ }
+}
+
+void OverlayDialog::StartInputThread() {
+ if (input_thread_running) {
+ return;
+ }
+
+ input_thread_running = true;
+
+ input_thread = std::thread(&OverlayDialog::InputThread, this);
+}
+
+void OverlayDialog::StopInputThread() {
+ input_thread_running = false;
+
+ if (input_thread.joinable()) {
+ input_thread.join();
+ }
+}
+
+void OverlayDialog::InputThread() {
+ while (input_thread_running) {
+ input_interpreter->PollInput();
+
+ HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::DLeft, HIDButton::DRight,
+ HIDButton::LStickLeft, HIDButton::LStickRight>();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+}
diff --git a/src/yuzu/util/overlay_dialog.h b/src/yuzu/util/overlay_dialog.h
new file mode 100644
index 000000000..e8c388bd0
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.h
@@ -0,0 +1,107 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <atomic>
+#include <memory>
+#include <thread>
+
+#include <QDialog>
+
+#include "common/common_types.h"
+
+enum class HIDButton : u8;
+
+class InputInterpreter;
+
+namespace Core {
+class System;
+}
+
+namespace Ui {
+class OverlayDialog;
+}
+
+/**
+ * An OverlayDialog is an interactive dialog that accepts controller input (while a game is running)
+ * This dialog attempts to replicate the look and feel of the Nintendo Switch's overlay dialogs and
+ * provide some extra features such as embedding HTML/Rich Text content in a QTextBrowser.
+ * The OverlayDialog provides 2 modes: one to embed regular text into a QLabel and another to embed
+ * HTML/Rich Text content into a QTextBrowser.
+ */
+class OverlayDialog final : public QDialog {
+ Q_OBJECT
+
+public:
+ explicit OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text,
+ const QString& body_text, const QString& left_button_text,
+ const QString& right_button_text,
+ Qt::Alignment alignment = Qt::AlignCenter, bool use_rich_text_ = false);
+ ~OverlayDialog() override;
+
+private:
+ /**
+ * Initializes a text dialog with a QLabel storing text.
+ * Only use this for short text as the dialog buttons would be squashed with longer text.
+ *
+ * @param title_text Title text to be displayed
+ * @param body_text Main text to be displayed
+ * @param left_button_text Left button text. If empty, the button is hidden and disabled
+ * @param right_button_text Right button text. If empty, the button is hidden and disabled
+ * @param alignment Main text alignment
+ */
+ void InitializeRegularTextDialog(const QString& title_text, const QString& body_text,
+ const QString& left_button_text,
+ const QString& right_button_text, Qt::Alignment alignment);
+
+ /**
+ * Initializes a text dialog with a QTextBrowser storing text.
+ * This is ideal for longer text or rich text content. A scrollbar is shown for longer text.
+ *
+ * @param title_text Title text to be displayed
+ * @param body_text Main text to be displayed
+ * @param left_button_text Left button text. If empty, the button is hidden and disabled
+ * @param right_button_text Right button text. If empty, the button is hidden and disabled
+ * @param alignment Main text alignment
+ */
+ void InitializeRichTextDialog(const QString& title_text, const QString& body_text,
+ const QString& left_button_text, const QString& right_button_text,
+ Qt::Alignment alignment);
+
+ /// Moves and resizes the dialog to be fully overlayed on top of the parent window.
+ void MoveAndResizeWindow();
+
+ /**
+ * Handles button presses and converts them into keyboard input.
+ *
+ * @tparam HIDButton The list of buttons that can be converted into keyboard input.
+ */
+ template <HIDButton... T>
+ void HandleButtonPressedOnce();
+
+ /**
+ * Translates a button press to focus or click either the left or right buttons.
+ *
+ * @param button The button press to process.
+ */
+ void TranslateButtonPress(HIDButton button);
+
+ void StartInputThread();
+ void StopInputThread();
+
+ /// The thread where input is being polled and processed.
+ void InputThread();
+
+ std::unique_ptr<Ui::OverlayDialog> ui;
+
+ bool use_rich_text;
+
+ std::unique_ptr<InputInterpreter> input_interpreter;
+
+ std::thread input_thread;
+
+ std::atomic<bool> input_thread_running{};
+};
diff --git a/src/yuzu/util/overlay_dialog.ui b/src/yuzu/util/overlay_dialog.ui
new file mode 100644
index 000000000..278e2f219
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.ui
@@ -0,0 +1,404 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>OverlayDialog</class>
+ <widget class="QDialog" name="OverlayDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1280</width>
+ <height>720</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="stackedDialog">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="lineDialog">
+ <layout class="QGridLayout" name="lineDialogGridLayout" rowstretch="210,300,210" columnstretch="250,780,250">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="1" column="1">
+ <widget class="QWidget" name="contentDialog" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_2" stretch="70,149,82">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_title">
+ <property name="font">
+ <font>
+ <pointsize>14</pointsize>
+ </font>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_dialog">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="buttonsDialog" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="button_cancel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="button_ok_label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="2">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="richDialog">
+ <layout class="QGridLayout" name="richDialogGridLayout" rowstretch="100,520,100" columnstretch="165,950,165">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1">
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="QWidget" name="contentRichDialog" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_3" stretch="70,368,82">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_title_rich">
+ <property name="font">
+ <font>
+ <pointsize>14</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextBrowser" name="text_browser_dialog">
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="html">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="buttonsRichDialog" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="button_cancel_rich">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="button_ok_rich">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../dist/icons/overlay/overlay.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt
index 8461f8896..4bf25727b 100644
--- a/src/yuzu_cmd/CMakeLists.txt
+++ b/src/yuzu_cmd/CMakeLists.txt
@@ -20,7 +20,6 @@ add_executable(yuzu-cmd
emu_window/emu_window_sdl2_gl.h
emu_window/emu_window_sdl2_vk.cpp
emu_window/emu_window_sdl2_vk.h
- resource.h
yuzu.cpp
yuzu.rc
)
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 43877fc98..7e1d5f379 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -4,13 +4,23 @@
#include <memory>
#include <sstream>
+
+// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+#endif
#include <SDL.h>
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
#include <inih/cpp/INIReader.h>
#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/param_package.h"
+#include "common/settings.h"
#include "core/hle/service/acc/profile_manager.h"
-#include "core/settings.h"
#include "input_common/main.h"
#include "input_common/udp/client.h"
#include "yuzu_cmd/config.h"
@@ -428,6 +438,10 @@ void Config::ReadValues() {
Settings::values.reporting_services =
sdl2_config->GetBoolean("Debugging", "reporting_services", false);
Settings::values.quest_flag = sdl2_config->GetBoolean("Debugging", "quest_flag", false);
+ Settings::values.use_debug_asserts =
+ sdl2_config->GetBoolean("Debugging", "use_debug_asserts", false);
+ Settings::values.use_auto_stub = sdl2_config->GetBoolean("Debugging", "use_auto_stub", false);
+
Settings::values.disable_macro_jit =
sdl2_config->GetBoolean("Debugging", "disable_macro_jit", false);
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 3ee0e037d..4ce8e08e4 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -325,6 +325,12 @@ dump_nso=false
# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode
# false: Retail/Normal Mode (default), true: Kiosk Mode
quest_flag =
+# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
+# false: Disabled (default), true: Enabled
+use_debug_asserts =
+# Determines whether unimplemented HLE service calls should be automatically stubbed.
+# false: Disabled (default), true: Enabled
+use_auto_stub =
# Enables/Disables the macro JIT compiler
disable_macro_jit=false
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index ce8b7c218..d64f81106 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -2,7 +2,16 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+#endif
#include <SDL.h>
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
#include "common/logging/log.h"
#include "common/scm_rev.h"
#include "core/core.h"
@@ -229,6 +238,6 @@ void EmuWindow_SDL2::SetWindowIcon() {
SDL_FreeSurface(window_icon);
}
-void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair<unsigned, unsigned> minimal_size) {
+void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) {
SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second);
}
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
index 0e17bbca7..1b9ab5b93 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -71,7 +71,7 @@ protected:
void Fullscreen();
/// Called when a configuration change affects the minimal size of the window
- void OnMinimalClientAreaChangeRequest(std::pair<unsigned, unsigned> minimal_size) override;
+ void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
/// Is the window still open?
bool is_open = true;
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index a02485c14..3c49a300b 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -5,16 +5,26 @@
#include <algorithm>
#include <cstdlib>
#include <string>
+
#define SDL_MAIN_HANDLED
+// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+#endif
#include <SDL.h>
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
#include <fmt/format.h>
#include <glad/glad.h>
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
-#include "core/settings.h"
#include "input_common/keyboard.h"
#include "input_common/main.h"
#include "video_core/renderer_base.h"
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index 6f9b00461..3401ad4b4 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -11,12 +11,20 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
-#include "core/settings.h"
+#include "common/settings.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h"
// Include these late to avoid polluting everything with Xlib macros
+// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+#endif
#include <SDL.h>
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
#include <SDL_syswm.h>
EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem)
diff --git a/src/yuzu_cmd/resource.h b/src/yuzu_cmd/resource.h
deleted file mode 100644
index df8e459e4..000000000
--- a/src/yuzu_cmd/resource.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by pcafe.rc
-//
-#define IDI_ICON3 103
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 105
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 982c41785..4871ac3bb 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -20,6 +20,7 @@
#include "common/nvidia_flags.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "common/telemetry.h"
#include "core/core.h"
@@ -29,7 +30,6 @@
#include "core/hle/kernel/process.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
-#include "core/settings.h"
#include "core/telemetry_session.h"
#include "input_common/main.h"
#include "video_core/renderer_base.h"
@@ -74,14 +74,16 @@ static void PrintVersion() {
}
static void InitializeLogging() {
+ using namespace Common;
+
Log::Filter log_filter(Log::Level::Debug);
log_filter.ParseFilterString(Settings::values.log_filter);
Log::SetGlobalFilter(log_filter);
Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
- const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir);
- Common::FS::CreateFullPath(log_dir);
+ const std::string& log_dir = FS::GetUserPath(FS::UserPath::LogDir);
+ FS::CreateFullPath(log_dir);
Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE));
#ifdef _WIN32
Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
@@ -164,7 +166,7 @@ int main(int argc, char** argv) {
InputCommon::InputSubsystem input_subsystem;
// Apply the command line arguments
- Settings::Apply(system);
+ system.ApplySettings();
std::unique_ptr<EmuWindow_SDL2> emu_window;
switch (Settings::values.renderer_backend.GetValue()) {