diff --git a/dist/icons/overlay/arrow_left.png b/dist/icons/overlay/arrow_left.png
new file mode 100644
index 000000000..a5d4fecfe
Binary files /dev/null and b/dist/icons/overlay/arrow_left.png 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
Binary files /dev/null and b/dist/icons/overlay/arrow_left_dark.png differ
diff --git a/dist/icons/overlay/arrow_right.png b/dist/icons/overlay/arrow_right.png
new file mode 100644
index 000000000..e47ee94bd
Binary files /dev/null and b/dist/icons/overlay/arrow_right.png 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
Binary files /dev/null and b/dist/icons/overlay/arrow_right_dark.png differ
diff --git a/dist/icons/overlay/button_A.png b/dist/icons/overlay/button_A.png
new file mode 100644
index 000000000..fd90f8b42
Binary files /dev/null and b/dist/icons/overlay/button_A.png 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
Binary files /dev/null and b/dist/icons/overlay/button_A_dark.png differ
diff --git a/dist/icons/overlay/button_B.png b/dist/icons/overlay/button_B.png
new file mode 100644
index 000000000..e8927addc
Binary files /dev/null and b/dist/icons/overlay/button_B.png 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
Binary files /dev/null and b/dist/icons/overlay/button_B_dark.png differ
diff --git a/dist/icons/overlay/button_L.png b/dist/icons/overlay/button_L.png
new file mode 100644
index 000000000..77838369e
Binary files /dev/null and b/dist/icons/overlay/button_L.png 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
Binary files /dev/null and b/dist/icons/overlay/button_L_dark.png differ
diff --git a/dist/icons/overlay/button_R.png b/dist/icons/overlay/button_R.png
new file mode 100644
index 000000000..4e5553954
Binary files /dev/null and b/dist/icons/overlay/button_R.png 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
Binary files /dev/null and b/dist/icons/overlay/button_R_dark.png differ
diff --git a/dist/icons/overlay/button_X.png b/dist/icons/overlay/button_X.png
new file mode 100644
index 000000000..fe70fb685
Binary files /dev/null and b/dist/icons/overlay/button_X.png 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
Binary files /dev/null and b/dist/icons/overlay/button_X_dark.png differ
diff --git a/dist/icons/overlay/button_Y.png b/dist/icons/overlay/button_Y.png
new file mode 100644
index 000000000..ca0de569d
Binary files /dev/null and b/dist/icons/overlay/button_Y.png 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
Binary files /dev/null and b/dist/icons/overlay/button_Y_dark.png differ
diff --git a/dist/icons/overlay/button_minus.png b/dist/icons/overlay/button_minus.png
new file mode 100644
index 000000000..7b315fe79
Binary files /dev/null and b/dist/icons/overlay/button_minus.png 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
Binary files /dev/null and b/dist/icons/overlay/button_minus_dark.png differ
diff --git a/dist/icons/overlay/button_plus.png b/dist/icons/overlay/button_plus.png
new file mode 100644
index 000000000..4d8090d7d
Binary files /dev/null and b/dist/icons/overlay/button_plus.png 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
Binary files /dev/null and b/dist/icons/overlay/button_plus_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/button_press_stick.png 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
Binary files /dev/null and b/dist/icons/overlay/button_press_stick_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_dual_joycon.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_dual_joycon_dark.png differ
diff --git a/dist/icons/overlay/controller_handheld.png b/dist/icons/overlay/controller_handheld.png
new file mode 100644
index 000000000..deb375011
Binary files /dev/null and b/dist/icons/overlay/controller_handheld.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_handheld_dark.png differ
diff --git a/dist/icons/overlay/controller_pro.png b/dist/icons/overlay/controller_pro.png
new file mode 100644
index 000000000..67cf86d5c
Binary files /dev/null and b/dist/icons/overlay/controller_pro.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_pro_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_a.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_a_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_b.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_b_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_x.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_x_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_y.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_left_y_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_right.png 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
Binary files /dev/null and b/dist/icons/overlay/controller_single_joycon_right_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_B.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_B_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_B_dark_disabled.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_B_disabled.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_Y.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_Y_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_Y_dark_disabled.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_Y_disabled.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_backspace.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_backspace_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_plus.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_plus_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_plus_dark_disabled.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_plus_disabled.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_shift.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_shift_dark.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_shift_lock_off.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_shift_lock_on.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_shift_on.png 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
Binary files /dev/null and b/dist/icons/overlay/osk_button_shift_on_dark.png 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/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 286e912e3..532e418b0 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
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;
 
-    out(parameters.initial_text);
+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::SendTextCheckDialog(
-    std::u16string error_message, std::function<void()> finished_check) const {
+void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() 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 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();
+}
+
+void DefaultSoftwareKeyboardApplet::HideInlineKeyboard() const {
+    LOG_WARNING(Service_AM,
+                "(STUBBED) called, backend requested to hide the inline software keyboard.");
+}
+
+void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_parameters) const {
+    LOG_WARNING(Service_AM,
+                "(STUBBED) called, backend requested to change the inline keyboard text.");
+
+    LOG_INFO(Service_AM,
+             "\nInlineTextParameters:"
+             "\ninput_text={}"
+             "\ncursor_position={}",
+             Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
+
+    submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
+                           text_parameters.input_text, text_parameters.cursor_position);
+}
+
+void DefaultSoftwareKeyboardApplet::ExitKeyboard() const {
+    LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to exit the software keyboard.");
+}
+
+void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const {
+    submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text);
+}
+
+void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const {
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+    for (std::size_t index = 0; index < text.size(); ++index) {
+        submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
+                               std::u16string(text.data(), text.data() + index + 1),
+                               static_cast<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;
+    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;
+};
 
-    union {
-        u8 value;
+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;
+};
 
-        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;
-    };
+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/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/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 416c5239a..c59054468 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -971,7 +971,7 @@ private:
 
         auto storage = applet->GetBroker().PopNormalDataToGame();
         if (storage == nullptr) {
-            LOG_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 +1002,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 +1125,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 +1134,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 +1160,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 +1180,65 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
 }
 
 void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
     IPC::RequestParser rp{ctx};
 
-    rp.SetCurrentOffset(3);
-    const auto handle{rp.Pop<Kernel::Handle>()};
+    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, "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;
+    }
+
+    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};
+
+    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, "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..aefbdf0d5 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -254,6 +254,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..5ddad851a 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -241,31 +241,31 @@ void AppletManager::ClearAll() {
     frontend = {};
 }
 
-std::shared_ptr<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..26b482015 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -62,6 +62,14 @@ 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_);
@@ -200,7 +208,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..a33f05f97 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_.Kernel()}, applet_mode{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..07cb92bf9 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;
@@ -119,6 +120,7 @@ public:
     void ConfigurationComplete();
 
 private:
+    LibraryAppletMode applet_mode;
     const Core::Frontend::ControllerApplet& frontend;
     Core::System& system;
 
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
index 0c8b632e8..a9f0a9c95 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_.Kernel()}, applet_mode{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..a3e520cd4 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;
@@ -40,6 +41,7 @@ public:
 private:
     union ErrorArguments;
 
+    LibraryAppletMode applet_mode;
     const Core::Frontend::ErrorApplet& frontend;
     ResultCode error_code = RESULT_SUCCESS;
     ErrorAppletMode mode = ErrorAppletMode::ShowError;
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index 4d1df5cbe..71016cce7 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_.Kernel()}, applet_mode{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_.Kernel()}, applet_mode{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_.Kernel()}, id{id_}, applet_mode{applet_mode_}, 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..d9e6d4384 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;
@@ -32,6 +33,7 @@ public:
     void AuthFinished(bool is_successful = true);
 
 private:
+    LibraryAppletMode applet_mode;
     Core::Frontend::ParentalControlsApplet& frontend;
     Core::System& system;
     bool complete = false;
@@ -50,7 +52,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;
@@ -62,6 +65,7 @@ public:
     void ViewFinished();
 
 private:
+    LibraryAppletMode applet_mode;
     const Core::Frontend::PhotoViewerApplet& frontend;
     bool complete = false;
     PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
@@ -70,7 +74,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;
@@ -82,6 +86,7 @@ public:
 
 private:
     AppletId id;
+    LibraryAppletMode applet_mode;
     Core::System& system;
 };
 
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index 77fba16c7..ab8b6fcc5 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_.Kernel()}, applet_mode{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..90f054030 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;
 
@@ -47,6 +47,7 @@ public:
     void SelectionComplete(std::optional<Common::UUID> uuid);
 
 private:
+    LibraryAppletMode applet_mode;
     const Core::Frontend::ProfileSelectApplet& frontend;
 
     UserSelectionConfig config;
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 79b209c6b..c3a05de9c 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;
-} // 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);
+// The maximum number of UTF-16 characters that can be input into the swkbd text field.
+constexpr u32 DEFAULT_MAX_TEXT_LENGTH = 500;
 
-    return params;
+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";
+    }
 }
 
-SoftwareKeyboard::SoftwareKeyboard(Core::System& system_,
-                                   const Core::Frontend::SoftwareKeyboardApplet& frontend_)
-    : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+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
+
+SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
+                                   Core::Frontend::SoftwareKeyboardApplet& frontend_)
+    : Applet{system_.Kernel()}, applet_mode{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();
+    LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}",
+             applet_mode);
 
-    if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) {
-        is_inline = true;
-        return;
+    LOG_DEBUG(Service_AM,
+              "Initializing Applet with common_args: arg_version={}, lib_version={}, "
+              "play_startup_sound={}, size={}, system_tick={}, theme_color={}",
+              common_args.arguments_version, common_args.library_version,
+              common_args.play_startup_sound, common_args.size, common_args.system_tick,
+              common_args.theme_color);
+
+    swkbd_applet_version = SwkbdAppletVersion{common_args.library_version};
+
+    switch (applet_mode) {
+    case LibraryAppletMode::AllForeground:
+        InitializeForeground();
+        break;
+    case LibraryAppletMode::Background:
+    case LibraryAppletMode::BackgroundIndirectDisplay:
+        InitializeBackground(applet_mode);
+        break;
+    default:
+        UNREACHABLE_MSG("Invalid LibraryAppletMode={}", applet_mode);
+        break;
     }
-
-    ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
-    std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
-
-    const auto work_buffer_storage = broker.PopNormalDataToApplet();
-    ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; });
-    const auto& work_buffer = work_buffer_storage->GetData();
-
-    if (config.initial_string_size == 0)
-        return;
-
-    std::vector<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());
 }
 
 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));
-
-        switch (request) {
-        case Request::Finalize:
-            complete = true;
-            broker.SignalStateChanged();
-            break;
-        case Request::Calc: {
-            broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1}));
-            broker.SignalStateChanged();
-            break;
-        }
-        default:
-            UNIMPLEMENTED_MSG("Request {:X} is not implemented", request);
-            break;
-        }
+        ProcessTextCheck();
     }
 }
 
 void SoftwareKeyboard::Execute() {
     if (complete) {
-        broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data)));
-        broker.SignalStateChanged();
         return;
     }
 
-    const auto parameters = ConvertToFrontendParameters(config, initial_text);
-    if (!is_inline) {
-        frontend.RequestText(
-            [this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters);
+    if (is_background) {
+        return;
     }
+
+    ShowNormalKeyboard();
 }
 
-void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
-    std::vector<u8> output_main(SWKBD_OUTPUT_BUFFER_SIZE);
+void SoftwareKeyboard::SubmitTextNormal(SwkbdResult result, std::u16string submitted_text) {
+    if (complete) {
+        return;
+    }
 
-    if (text.has_value()) {
-        std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE);
-
-        if (config.utf_8) {
-            const u64 size = text->size() + sizeof(u64);
-            const auto new_text = Common::UTF16ToUTF8(*text);
-
-            std::memcpy(output_sub.data(), &size, sizeof(u64));
-            std::memcpy(output_sub.data() + 8, new_text.data(),
-                        std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 8));
-
-            output_main[0] = INTERACTIVE_STATUS_OK;
-            std::memcpy(output_main.data() + 4, new_text.data(),
-                        std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4));
-        } else {
-            const u64 size = text->size() * 2 + sizeof(u64);
-            std::memcpy(output_sub.data(), &size, sizeof(u64));
-            std::memcpy(output_sub.data() + 8, text->data(),
-                        std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8));
-
-            output_main[0] = INTERACTIVE_STATUS_OK;
-            std::memcpy(output_main.data() + 4, text->data(),
-                        std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4));
-        }
-
-        complete = !config.text_check;
-        final_data = output_main;
-
-        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)));
-        }
+    if (swkbd_config_common.use_text_check && result == SwkbdResult::Ok) {
+        SubmitForTextCheck(submitted_text);
     } else {
-        output_main[0] = 1;
-        complete = true;
-        broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(output_main)));
-        broker.SignalStateChanged();
+        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 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:
+            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::InitializeForeground() {
+    LOG_INFO(Service_AM, "Initializing Normal Software Keyboard Applet.");
+
+    is_background = false;
+
+    const auto swkbd_config_storage = broker.PopNormalDataToApplet();
+    ASSERT(swkbd_config_storage != nullptr);
+
+    const auto& swkbd_config_data = swkbd_config_storage->GetData();
+    ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon));
+
+    std::memcpy(&swkbd_config_common, swkbd_config_data.data(), sizeof(SwkbdConfigCommon));
+
+    switch (swkbd_applet_version) {
+    case SwkbdAppletVersion::Version5:
+    case SwkbdAppletVersion::Version65542:
+        ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld));
+        std::memcpy(&swkbd_config_old, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
+                    sizeof(SwkbdConfigOld));
+        break;
+    case SwkbdAppletVersion::Version196615:
+    case SwkbdAppletVersion::Version262152:
+    case SwkbdAppletVersion::Version327689:
+        ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld2));
+        std::memcpy(&swkbd_config_old2, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
+                    sizeof(SwkbdConfigOld2));
+        break;
+    case SwkbdAppletVersion::Version393227:
+    case SwkbdAppletVersion::Version524301:
+        ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew));
+        std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
+                    sizeof(SwkbdConfigNew));
+        break;
+    default:
+        UNIMPLEMENTED_MSG("Unknown SwkbdConfig revision={} with size={}", swkbd_applet_version,
+                          swkbd_config_data.size());
+        ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew));
+        std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
+                    sizeof(SwkbdConfigNew));
+        break;
+    }
+
+    const auto work_buffer_storage = broker.PopNormalDataToApplet();
+    ASSERT(work_buffer_storage != nullptr);
+
+    if (swkbd_config_common.initial_string_length == 0) {
+        InitializeFrontendKeyboard();
+        return;
+    }
+
+    const auto& work_buffer = work_buffer_storage->GetData();
+
+    std::vector<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::ProcessInlineKeyboardRequest() {
+    const auto request_data_storage = broker.PopInteractiveDataToApplet();
+    ASSERT(request_data_storage != nullptr);
+
+    const auto& request_data = request_data_storage->GetData();
+    ASSERT(request_data.size() >= sizeof(SwkbdRequestCommand));
+
+    SwkbdRequestCommand request_command;
+
+    std::memcpy(&request_command, request_data.data(), sizeof(SwkbdRequestCommand));
+
+    switch (request_command) {
+    case SwkbdRequestCommand::Finalize:
+        RequestFinalize(request_data);
+        break;
+    case SwkbdRequestCommand::SetUserWordInfo:
+        RequestSetUserWordInfo(request_data);
+        break;
+    case SwkbdRequestCommand::SetCustomizeDic:
+        RequestSetCustomizeDic(request_data);
+        break;
+    case SwkbdRequestCommand::Calc:
+        RequestCalc(request_data);
+        break;
+    case SwkbdRequestCommand::SetCustomizedDictionaries:
+        RequestSetCustomizedDictionaries(request_data);
+        break;
+    case SwkbdRequestCommand::UnsetCustomizedDictionaries:
+        RequestUnsetCustomizedDictionaries(request_data);
+        break;
+    case SwkbdRequestCommand::SetChangedStringV2Flag:
+        RequestSetChangedStringV2Flag(request_data);
+        break;
+    case SwkbdRequestCommand::SetMovedCursorV2Flag:
+        RequestSetMovedCursorV2Flag(request_data);
+        break;
+    default:
+        UNIMPLEMENTED_MSG("Unknown SwkbdRequestCommand={}", request_command);
+        break;
+    }
+}
+
+void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result,
+                                                 std::u16string submitted_text) {
+    std::vector<u8> out_data(sizeof(SwkbdResult) + STRING_BUFFER_SIZE);
+
+    if (swkbd_config_common.use_utf8) {
+        std::string utf8_submitted_text = Common::UTF16ToUTF8(submitted_text);
+
+        LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-8 Submitted Text: {}", result,
+                  utf8_submitted_text);
+
+        std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
+        std::memcpy(out_data.data() + sizeof(SwkbdResult), utf8_submitted_text.data(),
+                    utf8_submitted_text.size());
+    } else {
+        LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-16 Submitted Text: {}", result,
+                  Common::UTF16ToUTF8(submitted_text));
+
+        std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
+        std::memcpy(out_data.data() + sizeof(SwkbdResult), submitted_text.data(),
+                    submitted_text.size() * sizeof(char16_t));
+    }
+
+    broker.PushNormalDataFromApplet(std::make_shared<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..85aeb4eb1 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,139 @@ 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();
+
+    LibraryAppletMode applet_mode;
+    Core::Frontend::SoftwareKeyboardApplet& frontend;
     Core::System& system;
+
+    SwkbdAppletVersion swkbd_applet_version;
+
+    SwkbdConfigCommon swkbd_config_common;
+    SwkbdConfigOld swkbd_config_old;
+    SwkbdConfigOld2 swkbd_config_old2;
+    SwkbdConfigNew swkbd_config_new;
+    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..b28b849bc 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_.Kernel()}, applet_mode{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..5eafbae7b 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;
 
@@ -63,6 +64,7 @@ private:
     void ExecuteWifi();
     void ExecuteLobby();
 
+    LibraryAppletMode applet_mode;
     const Core::Frontend::WebBrowserApplet& frontend;
 
     bool complete{false};
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"
 
-QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator(
-    Core::Frontend::SoftwareKeyboardParameters parameters)
-    : parameters(std::move(parameters)) {}
+namespace {
 
-QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const {
-    if (input.size() > static_cast<s64>(parameters.max_length)) {
-        return Invalid;
-    }
-    if (parameters.disable_space && input.contains(QLatin1Char{' '})) {
-        return Invalid;
-    }
-    if (parameters.disable_address && input.contains(QLatin1Char{'@'})) {
-        return Invalid;
-    }
-    if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) {
-        return Invalid;
-    }
-    if (parameters.disable_slash &&
-        (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) {
-        return Invalid;
-    }
-    if (parameters.disable_number &&
-        std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) {
-        return Invalid;
-    }
+using namespace Service::AM::Applets;
 
-    if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) {
-            return c == QLatin1Char{'O'} || c == QLatin1Char{'I'};
-        })) {
-        return Invalid;
-    }
+constexpr float BASE_HEADER_FONT_SIZE = 23.0f;
+constexpr float BASE_SUB_FONT_SIZE = 17.0f;
+constexpr float BASE_EDITOR_FONT_SIZE = 26.0f;
+constexpr float BASE_CHAR_BUTTON_FONT_SIZE = 28.0f;
+constexpr float BASE_LABEL_BUTTON_FONT_SIZE = 18.0f;
+constexpr float BASE_ICON_BUTTON_SIZE = 36.0f;
+[[maybe_unused]] constexpr float BASE_WIDTH = 1280.0f;
+constexpr float BASE_HEIGHT = 720.0f;
 
-    return Acceptable;
-}
+} // Anonymous namespace
 
 QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
-    QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_)
-    : QDialog(parent), parameters(std::move(parameters_)) {
-    layout = new QVBoxLayout;
+    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);
 
-    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:"));
+    setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint |
+                   Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint);
+    setWindowModality(Qt::WindowModal);
+    setAttribute(Qt::WA_DeleteOnClose);
+    setAttribute(Qt::WA_TranslucentBackground);
 
-    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());
+    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,
+            },
+        }},
+    }};
 
-    guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text));
-    guide_label->setHidden(parameters.guide_text.empty());
+    numberpad_buttons = {{
+        {
+            ui->button_1_num,
+            ui->button_2_num,
+            ui->button_3_num,
+            ui->button_backspace_num,
+        },
+        {
+            ui->button_4_num,
+            ui->button_5_num,
+            ui->button_6_num,
+            ui->button_ok_num,
+        },
+        {
+            ui->button_7_num,
+            ui->button_8_num,
+            ui->button_9_num,
+            ui->button_ok_num,
+        },
+        {
+            nullptr,
+            ui->button_0_num,
+            nullptr,
+            ui->button_ok_num,
+        },
+    }};
 
-    length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length));
-    length_label->setAlignment(Qt::AlignRight);
-    length_label->setFont({length_label->font().family(), 8});
+    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,
+    };
 
-    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);
+    SetupMouseHover();
 
-    connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) {
-        length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length));
-    });
-
-    buttons = new QDialogButtonBox(QDialogButtonBox::Cancel);
-    if (parameters.submit_text.empty()) {
-        buttons->addButton(QDialogButtonBox::Ok);
-    } else {
-        buttons->addButton(QString::fromStdU16String(parameters.submit_text),
-                           QDialogButtonBox::AcceptRole);
+    if (!initialize_parameters.ok_text.empty()) {
+        ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text));
+    }
+
+    ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text));
+    ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text));
+
+    current_text = initialize_parameters.initial_text;
+    cursor_position = initialize_parameters.initial_cursor_position;
+
+    SetTextDrawType();
+
+    for (auto* button : all_buttons) {
+        connect(button, &QPushButton::clicked, this, [this, button](bool) {
+            if (is_inline) {
+                InlineKeyboardButtonClicked(button);
+            } else {
+                NormalKeyboardButtonClicked(button);
+            }
+        });
+    }
+
+    // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
+    if (system.IsPoweredOn()) {
+        input_interpreter = std::make_unique<InputInterpreter>(system);
     }
-    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;
+QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() {
+    StopInputThread();
+}
 
-void QtSoftwareKeyboardDialog::accept() {
-    text = line_edit->text().toStdU16String();
-    QDialog::accept();
+void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) {
+    if (isVisible()) {
+        return;
+    }
+
+    MoveAndResizeWindow(pos, size);
+
+    SetKeyboardType();
+    SetPasswordMode();
+    SetControllerImage();
+    DisableKeyboardButtons();
+    SetBackspaceOkEnabled();
+
+    open();
+}
+
+void QtSoftwareKeyboardDialog::ShowTextCheckDialog(
+    Service::AM::Applets::SwkbdTextCheckResult text_check_result,
+    std::u16string text_check_message) {
+    switch (text_check_result) {
+    case SwkbdTextCheckResult::Success:
+    case SwkbdTextCheckResult::Silent:
+    default:
+        break;
+    case SwkbdTextCheckResult::Failure: {
+        StopInputThread();
+
+        OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message),
+                             QString{}, tr("OK"), Qt::AlignCenter);
+        dialog.exec();
+
+        StartInputThread();
+        break;
+    }
+    case SwkbdTextCheckResult::Confirm: {
+        StopInputThread();
+
+        OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message),
+                             tr("Cancel"), tr("OK"), Qt::AlignCenter);
+        if (dialog.exec() == QDialog::Accepted) {
+            emit SubmitNormalText(SwkbdResult::Ok, current_text);
+            break;
+        }
+
+        StartInputThread();
+        break;
+    }
+    }
+}
+
+void QtSoftwareKeyboardDialog::ShowInlineKeyboard(
+    Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, QSize size) {
+    MoveAndResizeWindow(pos, size);
+
+    ui->topOSK->setStyleSheet(QStringLiteral("background: rgba(0, 0, 0, 0);"));
+
+    ui->headerOSK->hide();
+    ui->subOSK->hide();
+    ui->inputOSK->hide();
+    ui->charactersOSK->hide();
+    ui->inputBoxOSK->hide();
+    ui->charactersBoxOSK->hide();
+
+    initialize_parameters.max_text_length = appear_parameters.max_text_length;
+    initialize_parameters.min_text_length = appear_parameters.min_text_length;
+    initialize_parameters.type = appear_parameters.type;
+    initialize_parameters.key_disable_flags = appear_parameters.key_disable_flags;
+    initialize_parameters.enable_backspace_button = appear_parameters.enable_backspace_button;
+    initialize_parameters.enable_return_button = appear_parameters.enable_return_button;
+    initialize_parameters.disable_cancel_button = initialize_parameters.disable_cancel_button;
+
+    SetKeyboardType();
+    SetControllerImage();
+    DisableKeyboardButtons();
+    SetBackspaceOkEnabled();
+
+    open();
+}
+
+void QtSoftwareKeyboardDialog::HideInlineKeyboard() {
+    StopInputThread();
+    QDialog::hide();
+}
+
+void QtSoftwareKeyboardDialog::InlineTextChanged(
+    Core::Frontend::InlineTextParameters text_parameters) {
+    current_text = text_parameters.input_text;
+    cursor_position = text_parameters.cursor_position;
+
+    SetBackspaceOkEnabled();
+}
+
+void QtSoftwareKeyboardDialog::ExitKeyboard() {
+    StopInputThread();
+    QDialog::done(QDialog::Accepted);
+}
+
+void QtSoftwareKeyboardDialog::open() {
+    QDialog::open();
+
+    row = 0;
+    column = 0;
+
+    const auto* const curr_button =
+        keyboard_buttons[static_cast<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() {
-    text.clear();
-    QDialog::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);
+    }
 }
 
-std::u16string QtSoftwareKeyboardDialog::GetText() const {
-    return text;
+void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) {
+    if (!is_inline) {
+        QDialog::keyPressEvent(event);
+        return;
+    }
+
+    const auto entered_key = event->key();
+
+    switch (entered_key) {
+    case Qt::Key_Escape:
+        QDialog::keyPressEvent(event);
+        return;
+    case Qt::Key_Backspace:
+        switch (bottom_osk_index) {
+        case BottomOSKIndex::LowerCase:
+            ui->button_backspace->click();
+            break;
+        case BottomOSKIndex::UpperCase:
+            ui->button_backspace_shift->click();
+            break;
+        case BottomOSKIndex::NumberPad:
+            ui->button_backspace_num->click();
+            break;
+        default:
+            break;
+        }
+        return;
+    case Qt::Key_Return:
+        switch (bottom_osk_index) {
+        case BottomOSKIndex::LowerCase:
+            ui->button_ok->click();
+            break;
+        case BottomOSKIndex::UpperCase:
+            ui->button_ok_shift->click();
+            break;
+        case BottomOSKIndex::NumberPad:
+            ui->button_ok_num->click();
+            break;
+        default:
+            break;
+        }
+        return;
+    case Qt::Key_Left:
+        MoveTextCursorDirection(Direction::Left);
+        return;
+    case Qt::Key_Right:
+        MoveTextCursorDirection(Direction::Right);
+        return;
+    default:
+        break;
+    }
+
+    const auto entered_text = event->text();
+
+    if (entered_text.isEmpty()) {
+        return;
+    }
+
+    InlineTextInsertString(entered_text.toStdU16String());
+}
+
+void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) {
+    QDialog::move(pos);
+    QDialog::resize(size);
+
+    // High DPI
+    const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f;
+
+    RescaleKeyboardElements(size.width(), size.height(), dpi_scale);
+}
+
+void QtSoftwareKeyboardDialog::RescaleKeyboardElements(float width, float height, float dpi_scale) {
+    const auto header_font_size = BASE_HEADER_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+    const auto sub_font_size = BASE_SUB_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+    const auto editor_font_size = BASE_EDITOR_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+    const auto char_button_font_size =
+        BASE_CHAR_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+    const auto label_button_font_size =
+        BASE_LABEL_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+
+    QFont header_font(QStringLiteral("MS Shell Dlg 2"), header_font_size, QFont::Normal);
+    QFont sub_font(QStringLiteral("MS Shell Dlg 2"), sub_font_size, QFont::Normal);
+    QFont editor_font(QStringLiteral("MS Shell Dlg 2"), editor_font_size, QFont::Normal);
+    QFont char_button_font(QStringLiteral("MS Shell Dlg 2"), char_button_font_size, QFont::Normal);
+    QFont label_button_font(QStringLiteral("MS Shell Dlg 2"), label_button_font_size,
+                            QFont::Normal);
+
+    ui->label_header->setFont(header_font);
+    ui->label_sub->setFont(sub_font);
+    ui->line_edit_osk->setFont(editor_font);
+    ui->text_edit_osk->setFont(editor_font);
+    ui->label_characters->setFont(sub_font);
+    ui->label_characters_box->setFont(sub_font);
+
+    ui->label_shift->setFont(label_button_font);
+    ui->label_shift_shift->setFont(label_button_font);
+    ui->label_cancel->setFont(label_button_font);
+    ui->label_cancel_shift->setFont(label_button_font);
+    ui->label_cancel_num->setFont(label_button_font);
+    ui->label_enter->setFont(label_button_font);
+    ui->label_enter_shift->setFont(label_button_font);
+    ui->label_enter_num->setFont(label_button_font);
+
+    for (auto* button : all_buttons) {
+        if (button == ui->button_return || button == ui->button_return_shift) {
+            button->setFont(label_button_font);
+            continue;
+        }
+
+        if (button == ui->button_space || button == ui->button_space_shift) {
+            button->setFont(label_button_font);
+            continue;
+        }
+
+        if (button == ui->button_shift || button == ui->button_shift_shift) {
+            button->setFont(label_button_font);
+            button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) *
+                                (height / BASE_HEIGHT));
+            continue;
+        }
+
+        if (button == ui->button_backspace || button == ui->button_backspace_shift ||
+            button == ui->button_backspace_num) {
+            button->setFont(label_button_font);
+            button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) *
+                                (height / BASE_HEIGHT));
+            continue;
+        }
+
+        if (button == ui->button_ok || button == ui->button_ok_shift ||
+            button == ui->button_ok_num) {
+            button->setFont(label_button_font);
+            continue;
+        }
+
+        button->setFont(char_button_font);
+    }
+}
+
+void QtSoftwareKeyboardDialog::SetKeyboardType() {
+    switch (initialize_parameters.type) {
+    case SwkbdType::Normal:
+    case SwkbdType::Qwerty:
+    case SwkbdType::Unknown3:
+    case SwkbdType::Latin:
+    case SwkbdType::SimplifiedChinese:
+    case SwkbdType::TraditionalChinese:
+    case SwkbdType::Korean:
+    default: {
+        bottom_osk_index = BottomOSKIndex::LowerCase;
+        ui->bottomOSK->setCurrentIndex(static_cast<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 {
+        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);
+    }
+}
+
+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;
+    }
+
+    if (key_disable_flags.numbers &&
+        std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return c.isDigit(); })) {
+        return false;
+    }
+
+    if (bottom_osk_index == BottomOSKIndex::NumberPad &&
+        std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return !c.isDigit(); })) {
+        return false;
+    }
+
+    return true;
+}
+
+void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() {
+    switch (bottom_osk_index) {
+    case BottomOSKIndex::LowerCase:
+        bottom_osk_index = BottomOSKIndex::UpperCase;
+        ui->bottomOSK->setCurrentIndex(static_cast<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;
+    }
+}
+
+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::SendTextCheckDialog(std::u16string error_message,
-                                             std::function<void()> finished_check_) const {
-    finished_check = std::move(finished_check_);
-    emit MainWindowTextCheckDialog(error_message);
+void QtSoftwareKeyboard::ShowNormalKeyboard() const {
+    emit MainWindowShowNormalKeyboard();
 }
 
-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::ShowTextCheckDialog(
+    Service::AM::Applets::SwkbdTextCheckResult text_check_result,
+    std::u16string text_check_message) const {
+    emit MainWindowShowTextCheckDialog(text_check_result, text_check_message);
 }
 
-void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() {
-    // Acquire the HLE mutex
-    std::lock_guard lock{HLE::g_hle_lock};
-    finished_check();
+void QtSoftwareKeyboard::ShowInlineKeyboard(
+    Core::Frontend::InlineAppearParameters appear_parameters) const {
+    LOG_INFO(Service_AM,
+             "\nInlineAppearParameters:"
+             "\nmax_text_length={}"
+             "\nmin_text_length={}"
+             "\nkey_top_scale_x={}"
+             "\nkey_top_scale_y={}"
+             "\nkey_top_translate_x={}"
+             "\nkey_top_translate_y={}"
+             "\ntype={}"
+             "\nkey_disable_flags={}"
+             "\nkey_top_as_floating={}"
+             "\nenable_backspace_button={}"
+             "\nenable_return_button={}"
+             "\ndisable_cancel_button={}",
+             appear_parameters.max_text_length, appear_parameters.min_text_length,
+             appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y,
+             appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y,
+             appear_parameters.type, appear_parameters.key_disable_flags.raw,
+             appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button,
+             appear_parameters.enable_return_button, appear_parameters.disable_cancel_button);
+
+    emit MainWindowShowInlineKeyboard(std::move(appear_parameters));
+}
+
+void QtSoftwareKeyboard::HideInlineKeyboard() const {
+    emit MainWindowHideInlineKeyboard();
+}
+
+void QtSoftwareKeyboard::InlineTextChanged(
+    Core::Frontend::InlineTextParameters text_parameters) const {
+    LOG_INFO(Service_AM,
+             "\nInlineTextParameters:"
+             "\ninput_text={}"
+             "\ncursor_position={}",
+             Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
+
+    emit MainWindowInlineTextChanged(std::move(text_parameters));
+}
+
+void QtSoftwareKeyboard::ExitKeyboard() const {
+    emit MainWindowExitKeyboard();
+}
+
+void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result,
+                                          std::u16string submitted_text) const {
+    submit_normal_callback(result, submitted_text);
+}
+
+void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
+                                          std::u16string submitted_text,
+                                          s32 cursor_position) const {
+    submit_inline_callback(reply_type, submitted_text, cursor_position);
 }
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"
 
+enum class HIDButton : u8;
+
+class InputInterpreter;
+
+namespace Core {
+class System;
+}
+
+namespace Ui {
+class QtSoftwareKeyboardDialog;
+}
+
 class GMainWindow;
-class QDialogButtonBox;
-class QLabel;
-class QLineEdit;
-class QVBoxLayout;
-class QtSoftwareKeyboard;
-
-class QtSoftwareKeyboardValidator final : public QValidator {
-public:
-    explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters);
-    State validate(QString& input, int& pos) const override;
-
-private:
-    Core::Frontend::SoftwareKeyboardParameters parameters;
-};
 
 class QtSoftwareKeyboardDialog final : public QDialog {
     Q_OBJECT
 
 public:
-    QtSoftwareKeyboardDialog(QWidget* parent,
-                             Core::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,
+    };
 
-    QDialogButtonBox* buttons;
-    QLabel* header_label;
-    QLabel* sub_label;
-    QLabel* guide_label;
-    QLabel* length_label;
-    QLineEdit* line_edit;
-    QVBoxLayout* layout;
+    enum class BottomOSKIndex {
+        LowerCase,
+        UpperCase,
+        NumberPad,
+    };
 
-    Core::Frontend::SoftwareKeyboardParameters parameters;
+    /**
+     * Moves and resizes the window to a specified position and size.
+     *
+     * @param pos Top-left window position
+     * @param size Window size
+     */
+    void MoveAndResizeWindow(QPoint pos, QSize size);
+
+    /**
+     * Rescales all keyboard elements to account for High DPI displays.
+     *
+     * @param width Window width
+     * @param height Window height
+     * @param dpi_scale Display scaling factor
+     */
+    void RescaleKeyboardElements(float width, float height, float dpi_scale);
+
+    /// Sets the keyboard type based on initialize_parameters.
+    void SetKeyboardType();
+
+    /// Sets the password mode based on initialize_parameters.
+    void SetPasswordMode();
+
+    /// Sets the text draw type based on initialize_parameters.
+    void SetTextDrawType();
+
+    /// Sets the controller image at the bottom left of the software keyboard.
+    void SetControllerImage();
+
+    /// Disables buttons based on initialize_parameters.
+    void DisableKeyboardButtons();
+
+    /// Changes whether the backspace or/and ok buttons should be enabled or disabled.
+    void SetBackspaceOkEnabled();
+
+    /**
+     * Validates the input text sent in based on the parameters in initialize_parameters.
+     *
+     * @param input_text Input text
+     *
+     * @returns True if the input text is valid, false otherwise.
+     */
+    bool ValidateInputText(const QString& input_text);
+
+    /// Switches between LowerCase and UpperCase (Shift and Caps Lock)
+    void ChangeBottomOSKIndex();
+
+    /// Processes a keyboard button click from the UI as normal keyboard input.
+    void NormalKeyboardButtonClicked(QPushButton* button);
+
+    /// Processes a keyboard button click from the UI as inline keyboard input.
+    void InlineKeyboardButtonClicked(QPushButton* button);
+
+    /**
+     * Inserts a string of arbitrary length into the current_text at the current cursor position.
+     * This is only used for the inline software keyboard.
+     */
+    void InlineTextInsertString(std::u16string_view string);
+
+    /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once.
+    void SetupMouseHover();
+
+    /**
+     * Handles button presses and converts them into keyboard input.
+     *
+     * @tparam HIDButton The list of buttons that can be converted into keyboard input.
+     */
+    template <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;
 
-    mutable std::function<void(std::optional<std::u16string>)> text_output;
-    mutable std::function<void()> finished_check;
+    void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
+                          std::u16string submitted_text, s32 cursor_position) const;
+
+    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/main.cpp b/src/yuzu/main.cpp
index fbf96be03..5f6cdc0c6 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -101,6 +101,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
 #include "core/perf_stats.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"
@@ -227,6 +228,8 @@ GMainWindow::GMainWindow()
     SetDiscordEnabled(UISettings::values.enable_discord_presence);
     discord_rpc->Update();
 
+    RegisterMetaTypes();
+
     InitializeWidgets();
     InitializeDebugWidgets();
     InitializeRecentFileMenuActions();
@@ -375,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());
@@ -414,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);
-
-    if (dialog.exec() == QDialog::Rejected) {
-        emit SoftwareKeyboardFinishedText(std::nullopt);
+void GMainWindow::SoftwareKeyboardInitialize(
+    bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) {
+    if (software_keyboard) {
+        LOG_ERROR(Frontend, "The software keyboard is already initialized!");
         return;
     }
 
-    emit SoftwareKeyboardFinishedText(dialog.GetText());
+    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::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) {
-    QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message));
-    emit SoftwareKeyboardFinishedCheckDialog();
+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;
+    }
+
+    software_keyboard->HideInlineKeyboard();
+}
+
+void GMainWindow::SoftwareKeyboardInlineTextChanged(
+    Core::Frontend::InlineTextParameters text_parameters) {
+    if (!software_keyboard) {
+        LOG_ERROR(Frontend, "The software keyboard is not initialized!");
+        return;
+    }
+
+    software_keyboard->InlineTextChanged(std::move(text_parameters));
+}
+
+void GMainWindow::SoftwareKeyboardExit() {
+    if (!software_keyboard) {
+        return;
+    }
+
+    software_keyboard->ExitKeyboard();
+
+    software_keyboard = nullptr;
 }
 
 void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
@@ -978,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);
 }
 
@@ -2187,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);
@@ -2244,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>