yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

Merge pull request #6133 from Morph1984/project-eleuthia

Project Eleuthia - On-Screen Keyboard and Error Applet Overlays
This commit is contained in:
bunnei 2021-04-16 23:03:23 -07:00 committed by GitHub
commit d5c1f3929c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
99 changed files with 9409 additions and 501 deletions

BIN
dist/icons/overlay/arrow_left.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
dist/icons/overlay/arrow_left_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B

BIN
dist/icons/overlay/arrow_right.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
dist/icons/overlay/arrow_right_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

BIN
dist/icons/overlay/button_A.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
dist/icons/overlay/button_A_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
dist/icons/overlay/button_B.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
dist/icons/overlay/button_B_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
dist/icons/overlay/button_L.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

BIN
dist/icons/overlay/button_L_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

BIN
dist/icons/overlay/button_R.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
dist/icons/overlay/button_R_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
dist/icons/overlay/button_X.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
dist/icons/overlay/button_X_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
dist/icons/overlay/button_Y.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
dist/icons/overlay/button_Y_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
dist/icons/overlay/button_minus.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
dist/icons/overlay/button_minus_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
dist/icons/overlay/button_plus.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
dist/icons/overlay/button_plus_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
dist/icons/overlay/controller_pro.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
dist/icons/overlay/osk_button_B.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

BIN
dist/icons/overlay/osk_button_B_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 B

BIN
dist/icons/overlay/osk_button_Y.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

BIN
dist/icons/overlay/osk_button_Y_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
dist/icons/overlay/osk_button_plus.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

BIN
dist/icons/overlay/osk_button_shift.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

64
dist/icons/overlay/overlay.qrc vendored Normal file
View File

@ -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>

View File

@ -281,3 +281,380 @@ QWidget#controllerPlayer7,
QWidget#controllerPlayer8 { QWidget#controllerPlayer8 {
background: transparent; 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);
}

View File

@ -1560,7 +1560,400 @@ QWidget#controllerPlayer8 {
background: transparent; background: transparent;
} }
/* touchscreen mapping widget */ QDialog#QtSoftwareKeyboardDialog,
TouchScreenPreview { QStackedWidget#topOSK {
qproperty-dotHighlightColor: #3daee9; 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;
} }

View File

@ -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 ----------------------------------------------------------- /* 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 plus three whitish (foreground) colors. Each set of widgets of the same
type have a header like this: type have a header like this:
------------------ ------------------
GroupName -------- GroupName --------
------------------ ------------------
And each widget is separated with a header like this: 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 This makes more easy to find and change some css field. The basic
configuration is described bellow. configuration is described bellow.
BACKGROUND ----------- BACKGROUND -----------
Light (unpressed) Light (unpressed)
Normal (border, disabled, pressed, checked, toolbars, menus) Normal (border, disabled, pressed, checked, toolbars, menus)
Dark (background) Dark (background)
FOREGROUND ----------- FOREGROUND -----------
Light (texts/labels) Light (texts/labels)
Normal (not used yet) Normal (not used yet)
Dark (disabled texts) Dark (disabled texts)
SELECTION ------------ SELECTION ------------
Light (selection/hover/active) Light (selection/hover/active)
Normal (selected) Normal (selected)
Dark (selected disabled) Dark (selected disabled)
If a stranger configuration is required because of a bugfix or anything 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 else, keep the comment on the line above so nobody changes it, including the
@ -2483,3 +2483,404 @@ QWidget#controllerPlayer7,
QWidget#controllerPlayer8 { QWidget#controllerPlayer8 {
background: transparent; 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);
}

View File

@ -273,6 +273,7 @@ add_library(core STATIC
hle/service/am/applets/profile_select.h hle/service/am/applets/profile_select.h
hle/service/am/applets/software_keyboard.cpp hle/service/am/applets/software_keyboard.cpp
hle/service/am/applets/software_keyboard.h 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.cpp
hle/service/am/applets/web_browser.h hle/service/am/applets/web_browser.h
hle/service/am/applets/web_types.h hle/service/am/applets/web_types.h

View File

@ -1,29 +1,149 @@
// Copyright 2018 yuzu emulator team // Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // 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 "common/string_util.h"
#include "core/frontend/applets/software_keyboard.h" #include "core/frontend/applets/software_keyboard.h"
namespace Core::Frontend { namespace Core::Frontend {
SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default;
void DefaultSoftwareKeyboardApplet::RequestText( DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default;
std::function<void(std::optional<std::u16string>)> out,
SoftwareKeyboardParameters parameters) const {
if (parameters.initial_text.empty())
out(u"yuzu");
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( void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const {
std::u16string error_message, std::function<void()> finished_check) const {
LOG_WARNING(Service_AM, LOG_WARNING(Service_AM,
"(STUBBED) called - Default fallback software keyboard does not support text " "(STUBBED) called, backend requested to show the normal software keyboard.");
"check! (error_message={})",
Common::UTF16ToUTF8(error_message)); SubmitNormalText(u"yuzu");
finished_check();
} }
void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog(
Service::AM::Applets::SwkbdTextCheckResult text_check_result,
std::u16string text_check_message) const {
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog.");
}
void DefaultSoftwareKeyboardApplet::ShowInlineKeyboard(
InlineAppearParameters appear_parameters) const {
LOG_WARNING(Service_AM,
"(STUBBED) called, backend requested to show the inline software keyboard.");
LOG_INFO(Service_AM,
"\nInlineAppearParameters:"
"\nmax_text_length={}"
"\nmin_text_length={}"
"\nkey_top_scale_x={}"
"\nkey_top_scale_y={}"
"\nkey_top_translate_x={}"
"\nkey_top_translate_y={}"
"\ntype={}"
"\nkey_disable_flags={}"
"\nkey_top_as_floating={}"
"\nenable_backspace_button={}"
"\nenable_return_button={}"
"\ndisable_cancel_button={}",
appear_parameters.max_text_length, appear_parameters.min_text_length,
appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y,
appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y,
appear_parameters.type, appear_parameters.key_disable_flags.raw,
appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button,
appear_parameters.enable_return_button, appear_parameters.disable_cancel_button);
std::thread([this] { SubmitInlineText(u"yuzu"); }).detach();
}
void DefaultSoftwareKeyboardApplet::HideInlineKeyboard() const {
LOG_WARNING(Service_AM,
"(STUBBED) called, backend requested to hide the inline software keyboard.");
}
void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_parameters) const {
LOG_WARNING(Service_AM,
"(STUBBED) called, backend requested to change the inline keyboard text.");
LOG_INFO(Service_AM,
"\nInlineTextParameters:"
"\ninput_text={}"
"\ncursor_position={}",
Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
text_parameters.input_text, text_parameters.cursor_position);
}
void DefaultSoftwareKeyboardApplet::ExitKeyboard() const {
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to exit the software keyboard.");
}
void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const {
submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text);
}
void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (std::size_t index = 0; index < text.size(); ++index) {
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
std::u16string(text.data(), text.data() + index + 1),
static_cast<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 } // namespace Core::Frontend

View File

@ -1,54 +1,116 @@
// Copyright 2018 yuzu emulator team // Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#pragma once #pragma once
#include <functional> #include <functional>
#include <optional> #include <thread>
#include <string>
#include "common/bit_field.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/am/applets/software_keyboard_types.h"
namespace Core::Frontend { namespace Core::Frontend {
struct SoftwareKeyboardParameters {
std::u16string submit_text; struct KeyboardInitializeParameters {
std::u16string ok_text;
std::u16string header_text; std::u16string header_text;
std::u16string sub_text; std::u16string sub_text;
std::u16string guide_text; std::u16string guide_text;
std::u16string initial_text; std::u16string initial_text;
std::size_t max_length; u32 max_text_length;
bool password; u32 min_text_length;
bool cursor_at_beginning; 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 { struct InlineAppearParameters {
u8 value; 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; struct InlineTextParameters {
BitField<2, 1, u8> disable_address; std::u16string input_text;
BitField<3, 1, u8> disable_percent; s32 cursor_position;
BitField<4, 1, u8> disable_slash;
BitField<6, 1, u8> disable_number;
BitField<7, 1, u8> disable_download_code;
};
}; };
class SoftwareKeyboardApplet { class SoftwareKeyboardApplet {
public: public:
virtual ~SoftwareKeyboardApplet(); virtual ~SoftwareKeyboardApplet();
virtual void RequestText(std::function<void(std::optional<std::u16string>)> out, virtual void InitializeKeyboard(
SoftwareKeyboardParameters parameters) const = 0; bool is_inline, KeyboardInitializeParameters initialize_parameters,
virtual void SendTextCheckDialog(std::u16string error_message, std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
std::function<void()> finished_check) const = 0; 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 { class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
public: public:
void RequestText(std::function<void(std::optional<std::u16string>)> out, ~DefaultSoftwareKeyboardApplet() override;
SoftwareKeyboardParameters parameters) const override;
void SendTextCheckDialog(std::u16string error_message, void InitializeKeyboard(
std::function<void()> finished_check) const override; 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 } // namespace Core::Frontend

View File

@ -12,7 +12,9 @@ InputInterpreter::InputInterpreter(Core::System& system)
: npad{system.ServiceManager() : npad{system.ServiceManager()
.GetService<Service::HID::Hid>("hid") .GetService<Service::HID::Hid>("hid")
->GetAppletResource() ->GetAppletResource()
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {} ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {
ResetButtonStates();
}
InputInterpreter::~InputInterpreter() = default; InputInterpreter::~InputInterpreter() = default;
@ -25,6 +27,17 @@ void InputInterpreter::PollInput() {
button_states[current_index] = button_state; 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 { bool InputInterpreter::IsButtonPressed(HIDButton button) const {
return (button_states[current_index] & (1U << static_cast<u8>(button))) != 0; return (button_states[current_index] & (1U << static_cast<u8>(button))) != 0;
} }

View File

@ -66,6 +66,9 @@ public:
/// Gets a button state from HID and inserts it into the array of button states. /// Gets a button state from HID and inserts it into the array of button states.
void PollInput(); void PollInput();
/// Resets all the button states to their defaults.
void ResetButtonStates();
/** /**
* Checks whether the button is pressed. * Checks whether the button is pressed.
* *

View File

@ -75,10 +75,14 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_
if (incoming) { if (incoming) {
// Populate the object lists with the data in the IPC request. // Populate the object lists with the data in the IPC request.
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { 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) { 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 { } else {
// For responses we just ignore the handles, they're empty and will be populated when // For responses we just ignore the handles, they're empty and will be populated when

View File

@ -210,6 +210,14 @@ public:
/// Helper function to test whether the output buffer at buffer_index can be written /// Helper function to test whether the output buffer at buffer_index can be written
bool CanWriteBuffer(std::size_t buffer_index = 0) const; 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> template <typename T>
std::shared_ptr<T> GetCopyObject(std::size_t index) { std::shared_ptr<T> GetCopyObject(std::size_t index) {
return DynamicObjectCast<T>(copy_objects.at(index)); return DynamicObjectCast<T>(copy_objects.at(index));
@ -285,6 +293,8 @@ private:
std::shared_ptr<Kernel::ServerSession> server_session; std::shared_ptr<Kernel::ServerSession> server_session;
std::shared_ptr<KThread> thread; std::shared_ptr<KThread> thread;
// TODO(yuriks): Check common usage of this and optimize size accordingly // 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> move_objects;
boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects; boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects;
boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects;

View File

@ -971,7 +971,7 @@ private:
auto storage = applet->GetBroker().PopNormalDataToGame(); auto storage = applet->GetBroker().PopNormalDataToGame();
if (storage == nullptr) { if (storage == nullptr) {
LOG_ERROR(Service_AM, LOG_DEBUG(Service_AM,
"storage is a nullptr. There is no data in the current normal channel"); "storage is a nullptr. There is no data in the current normal channel");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_DATA_IN_CHANNEL); rb.Push(ERR_NO_DATA_IN_CHANNEL);
@ -1002,7 +1002,7 @@ private:
auto storage = applet->GetBroker().PopInteractiveDataToGame(); auto storage = applet->GetBroker().PopInteractiveDataToGame();
if (storage == nullptr) { if (storage == nullptr) {
LOG_ERROR(Service_AM, LOG_DEBUG(Service_AM,
"storage is a nullptr. There is no data in the current interactive channel"); "storage is a nullptr. There is no data in the current interactive channel");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_DATA_IN_CHANNEL); rb.Push(ERR_NO_DATA_IN_CHANNEL);
@ -1125,7 +1125,7 @@ ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
{2, nullptr, "AreAnyLibraryAppletsLeft"}, {2, nullptr, "AreAnyLibraryAppletsLeft"},
{10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
{11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
{12, nullptr, "CreateHandleStorage"}, {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
}; };
RegisterHandlers(functions); RegisterHandlers(functions);
} }
@ -1134,14 +1134,15 @@ ILibraryAppletCreator::~ILibraryAppletCreator() = default;
void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto applet_id = rp.PopRaw<Applets::AppletId>(); 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, LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
applet_mode); applet_mode);
const auto& applet_manager{system.GetAppletManager()}; 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) { if (applet == nullptr) {
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); 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) { void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 size{rp.Pop<u64>()};
const s64 size{rp.Pop<s64>()};
LOG_DEBUG(Service_AM, "called, size={}", size); 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); std::vector<u8> buffer(size);
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@ -1170,18 +1180,65 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
} }
void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) { void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
rp.SetCurrentOffset(3); struct Parameters {
const auto handle{rp.Pop<Kernel::Handle>()}; 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 = auto transfer_mem =
system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
if (transfer_mem == nullptr) { 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}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_UNKNOWN); rb.Push(RESULT_UNKNOWN);
return; return;

View File

@ -254,6 +254,7 @@ private:
void CreateLibraryApplet(Kernel::HLERequestContext& ctx); void CreateLibraryApplet(Kernel::HLERequestContext& ctx);
void CreateStorage(Kernel::HLERequestContext& ctx); void CreateStorage(Kernel::HLERequestContext& ctx);
void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx);
void CreateHandleStorage(Kernel::HLERequestContext& ctx);
}; };
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {

View File

@ -241,31 +241,31 @@ void AppletManager::ClearAll() {
frontend = {}; frontend = {};
} }
std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const { std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const {
switch (id) { switch (id) {
case AppletId::Auth: 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: case AppletId::Controller:
return std::make_shared<Controller>(system, *frontend.controller); return std::make_shared<Controller>(system, mode, *frontend.controller);
case AppletId::Error: case AppletId::Error:
return std::make_shared<Error>(system, *frontend.error); return std::make_shared<Error>(system, mode, *frontend.error);
case AppletId::ProfileSelect: 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: 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::Web:
case AppletId::Shop: case AppletId::Shop:
case AppletId::OfflineWeb: case AppletId::OfflineWeb:
case AppletId::LoginShare: case AppletId::LoginShare:
case AppletId::WebAuth: 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: case AppletId::PhotoViewer:
return std::make_shared<PhotoViewer>(system, *frontend.photo_viewer); return std::make_shared<PhotoViewer>(system, mode, *frontend.photo_viewer);
default: default:
UNIMPLEMENTED_MSG( UNIMPLEMENTED_MSG(
"No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
static_cast<u8>(id)); static_cast<u8>(id));
return std::make_shared<StubApplet>(system, id); return std::make_shared<StubApplet>(system, id, mode);
} }
} }

View File

@ -62,6 +62,14 @@ enum class AppletId : u32 {
MyPage = 0x1A, MyPage = 0x1A,
}; };
enum class LibraryAppletMode : u32 {
AllForeground = 0,
Background = 1,
NoUI = 2,
BackgroundIndirectDisplay = 3,
AllForegroundInitiallyHidden = 4,
};
class AppletDataBroker final { class AppletDataBroker final {
public: public:
explicit AppletDataBroker(Kernel::KernelCore& kernel_); explicit AppletDataBroker(Kernel::KernelCore& kernel_);
@ -200,7 +208,7 @@ public:
void SetDefaultAppletsIfMissing(); void SetDefaultAppletsIfMissing();
void ClearAll(); void ClearAll();
std::shared_ptr<Applet> GetApplet(AppletId id) const; std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const;
private: private:
AppletFrontendSet frontend; AppletFrontendSet frontend;

View File

@ -45,8 +45,9 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
}; };
} }
Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_) Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_,
: Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} const Core::Frontend::ControllerApplet& frontend_)
: Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
Controller::~Controller() = default; Controller::~Controller() = default;

View File

@ -106,7 +106,8 @@ static_assert(sizeof(ControllerSupportResultInfo) == 0xC,
class Controller final : public Applet { class Controller final : public Applet {
public: 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; ~Controller() override;
void Initialize() override; void Initialize() override;
@ -119,6 +120,7 @@ public:
void ConfigurationComplete(); void ConfigurationComplete();
private: private:
LibraryAppletMode applet_mode;
const Core::Frontend::ControllerApplet& frontend; const Core::Frontend::ControllerApplet& frontend;
Core::System& system; Core::System& system;

View File

@ -86,8 +86,9 @@ ResultCode Decode64BitError(u64 error) {
} // Anonymous namespace } // Anonymous namespace
Error::Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_) Error::Error(Core::System& system_, LibraryAppletMode applet_mode_,
: Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} const Core::Frontend::ErrorApplet& frontend_)
: Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
Error::~Error() = default; Error::~Error() = default;

View File

@ -25,7 +25,8 @@ enum class ErrorAppletMode : u8 {
class Error final : public Applet { class Error final : public Applet {
public: 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; ~Error() override;
void Initialize() override; void Initialize() override;
@ -40,6 +41,7 @@ public:
private: private:
union ErrorArguments; union ErrorArguments;
LibraryAppletMode applet_mode;
const Core::Frontend::ErrorApplet& frontend; const Core::Frontend::ErrorApplet& frontend;
ResultCode error_code = RESULT_SUCCESS; ResultCode error_code = RESULT_SUCCESS;
ErrorAppletMode mode = ErrorAppletMode::ShowError; ErrorAppletMode mode = ErrorAppletMode::ShowError;

View File

@ -37,8 +37,9 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix)
} }
} }
Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_) Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_,
: Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} Core::Frontend::ParentalControlsApplet& frontend_)
: Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
Auth::~Auth() = default; Auth::~Auth() = default;
@ -152,8 +153,9 @@ void Auth::AuthFinished(bool is_successful) {
broker.SignalStateChanged(); broker.SignalStateChanged();
} }
PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_) PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
: Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} const Core::Frontend::PhotoViewerApplet& frontend_)
: Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
PhotoViewer::~PhotoViewer() = default; PhotoViewer::~PhotoViewer() = default;
@ -202,8 +204,8 @@ void PhotoViewer::ViewFinished() {
broker.SignalStateChanged(); broker.SignalStateChanged();
} }
StubApplet::StubApplet(Core::System& system_, AppletId id_) StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_)
: Applet{system_.Kernel()}, id{id_}, system{system_} {} : Applet{system_.Kernel()}, id{id_}, applet_mode{applet_mode_}, system{system_} {}
StubApplet::~StubApplet() = default; StubApplet::~StubApplet() = default;

View File

@ -20,7 +20,8 @@ enum class AuthAppletType : u32 {
class Auth final : public Applet { class Auth final : public Applet {
public: public:
explicit Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_); explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_,
Core::Frontend::ParentalControlsApplet& frontend_);
~Auth() override; ~Auth() override;
void Initialize() override; void Initialize() override;
@ -32,6 +33,7 @@ public:
void AuthFinished(bool is_successful = true); void AuthFinished(bool is_successful = true);
private: private:
LibraryAppletMode applet_mode;
Core::Frontend::ParentalControlsApplet& frontend; Core::Frontend::ParentalControlsApplet& frontend;
Core::System& system; Core::System& system;
bool complete = false; bool complete = false;
@ -50,7 +52,8 @@ enum class PhotoViewerAppletMode : u8 {
class PhotoViewer final : public Applet { class PhotoViewer final : public Applet {
public: 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; ~PhotoViewer() override;
void Initialize() override; void Initialize() override;
@ -62,6 +65,7 @@ public:
void ViewFinished(); void ViewFinished();
private: private:
LibraryAppletMode applet_mode;
const Core::Frontend::PhotoViewerApplet& frontend; const Core::Frontend::PhotoViewerApplet& frontend;
bool complete = false; bool complete = false;
PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
@ -70,7 +74,7 @@ private:
class StubApplet final : public Applet { class StubApplet final : public Applet {
public: public:
explicit StubApplet(Core::System& system_, AppletId id_); explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_);
~StubApplet() override; ~StubApplet() override;
void Initialize() override; void Initialize() override;
@ -82,6 +86,7 @@ public:
private: private:
AppletId id; AppletId id;
LibraryAppletMode applet_mode;
Core::System& system; Core::System& system;
}; };

View File

@ -15,9 +15,9 @@ namespace Service::AM::Applets {
constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; 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_) 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; ProfileSelect::~ProfileSelect() = default;

View File

@ -33,7 +33,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
class ProfileSelect final : public Applet { class ProfileSelect final : public Applet {
public: public:
explicit ProfileSelect(Core::System& system_, explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::ProfileSelectApplet& frontend_); const Core::Frontend::ProfileSelectApplet& frontend_);
~ProfileSelect() override; ~ProfileSelect() override;
@ -47,6 +47,7 @@ public:
void SelectionComplete(std::optional<Common::UUID> uuid); void SelectionComplete(std::optional<Common::UUID> uuid);
private: private:
LibraryAppletMode applet_mode;
const Core::Frontend::ProfileSelectApplet& frontend; const Core::Frontend::ProfileSelectApplet& frontend;
UserSelectionConfig config; UserSelectionConfig config;

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,14 @@
// Copyright 2018 yuzu emulator team // Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#pragma once #pragma once
#include <array>
#include <string>
#include <vector>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.h" #include "core/hle/result.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h" #include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applets/software_keyboard_types.h"
union ResultCode;
namespace Core { namespace Core {
class System; class System;
@ -22,45 +16,10 @@ class System;
namespace Service::AM::Applets { 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 { class SoftwareKeyboard final : public Applet {
public: public:
explicit SoftwareKeyboard(Core::System& system_, explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::SoftwareKeyboardApplet& frontend_); Core::Frontend::SoftwareKeyboardApplet& frontend_);
~SoftwareKeyboard() override; ~SoftwareKeyboard() override;
void Initialize() override; void Initialize() override;
@ -70,17 +29,139 @@ public:
void ExecuteInteractive() override; void ExecuteInteractive() override;
void Execute() 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: private:
const Core::Frontend::SoftwareKeyboardApplet& frontend; /// Initializes the normal software keyboard.
void InitializeForeground();
KeyboardConfig config; /// Initializes the inline software keyboard.
std::u16string initial_text; void InitializeBackground(LibraryAppletMode applet_mode);
bool complete = false;
bool is_inline = false; /// Processes the text check sent by the application.
std::vector<u8> final_data; 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; 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 } // namespace Service::AM::Applets

View File

@ -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

View File

@ -208,8 +208,9 @@ void ExtractSharedFonts(Core::System& system) {
} // namespace } // namespace
WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_) WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
: Applet{system_.Kernel()}, frontend(frontend_), system{system_} {} const Core::Frontend::WebBrowserApplet& frontend_)
: Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend(frontend_), system{system_} {}
WebBrowser::~WebBrowser() = default; WebBrowser::~WebBrowser() = default;

View File

@ -25,7 +25,8 @@ namespace Service::AM::Applets {
class WebBrowser final : public Applet { class WebBrowser final : public Applet {
public: public:
WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_); WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::WebBrowserApplet& frontend_);
~WebBrowser() override; ~WebBrowser() override;
@ -63,6 +64,7 @@ private:
void ExecuteWifi(); void ExecuteWifi();
void ExecuteLobby(); void ExecuteLobby();
LibraryAppletMode applet_mode;
const Core::Frontend::WebBrowserApplet& frontend; const Core::Frontend::WebBrowserApplet& frontend;
bool complete{false}; bool complete{false};

View File

@ -18,6 +18,7 @@ add_executable(yuzu
applets/profile_select.h applets/profile_select.h
applets/software_keyboard.cpp applets/software_keyboard.cpp
applets/software_keyboard.h applets/software_keyboard.h
applets/software_keyboard.ui
applets/web_browser.cpp applets/web_browser.cpp
applets/web_browser.h applets/web_browser.h
bootmanager.cpp bootmanager.cpp
@ -143,6 +144,9 @@ add_executable(yuzu
uisettings.h uisettings.h
util/limitable_input_dialog.cpp util/limitable_input_dialog.cpp
util/limitable_input_dialog.h 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.cpp
util/sequence_dialog/sequence_dialog.h util/sequence_dialog/sequence_dialog.h
util/url_request_interceptor.cpp util/url_request_interceptor.cpp

View File

@ -19,11 +19,11 @@ QtErrorDisplay::~QtErrorDisplay() = default;
void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const { void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const {
callback = std::move(finished); callback = std::move(finished);
emit MainWindowDisplayError( emit MainWindowDisplayError(
tr("An error has occurred.\nPlease try again or contact the developer of the " tr("Error Code: %1-%2 (0x%3)")
"software.\n\nError Code: %1-%2 (0x%3)")
.arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
.arg(error.description, 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, 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()); const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count());
emit MainWindowDisplayError( emit MainWindowDisplayError(
tr("An error occurred on %1 at %2.\nPlease try again or contact the " tr("Error Code: %1-%2 (0x%3)")
"developer of the software.\n\nError Code: %3-%4 (0x%5)")
.arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy")))
.arg(date_time.toString(QStringLiteral("h:mm:ss A")))
.arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
.arg(error.description, 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, 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 { std::function<void()> finished) const {
callback = std::move(finished); callback = std::move(finished);
emit MainWindowDisplayError( 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(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
.arg(error.description, 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(dialog_text))
.arg(QString::fromStdString(fullscreen_text))); .arg(QString::fromStdString(fullscreen_text)));
} }

View File

@ -24,7 +24,7 @@ public:
std::function<void()> finished) const override; std::function<void()> finished) const override;
signals: signals:
void MainWindowDisplayError(QString error) const; void MainWindowDisplayError(QString error_code, QString error_text) const;
private: private:
void MainWindowFinishedError(); void MainWindowFinishedError();

File diff suppressed because it is too large Load Diff

View File

@ -1,54 +1,228 @@
// Copyright 2018 yuzu Emulator Project // Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#pragma once #pragma once
#include <array>
#include <atomic>
#include <memory>
#include <thread>
#include <QDialog> #include <QDialog>
#include <QValidator> #include <QValidator>
#include "core/frontend/applets/software_keyboard.h" #include "core/frontend/applets/software_keyboard.h"
enum class HIDButton : u8;
class InputInterpreter;
namespace Core {
class System;
}
namespace Ui {
class QtSoftwareKeyboardDialog;
}
class GMainWindow; 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 { class QtSoftwareKeyboardDialog final : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
QtSoftwareKeyboardDialog(QWidget* parent, QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_,
Core::Frontend::SoftwareKeyboardParameters parameters); Core::Frontend::KeyboardInitializeParameters initialize_parameters_);
~QtSoftwareKeyboardDialog() override; ~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; 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: private:
std::u16string text; enum class Direction {
Left,
Up,
Right,
Down,
};
QDialogButtonBox* buttons; enum class BottomOSKIndex {
QLabel* header_label; LowerCase,
QLabel* sub_label; UpperCase,
QLabel* guide_label; NumberPad,
QLabel* length_label; };
QLineEdit* line_edit;
QVBoxLayout* layout;
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 { class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet {
@ -58,19 +232,54 @@ public:
explicit QtSoftwareKeyboard(GMainWindow& parent); explicit QtSoftwareKeyboard(GMainWindow& parent);
~QtSoftwareKeyboard() override; ~QtSoftwareKeyboard() override;
void RequestText(std::function<void(std::optional<std::u16string>)> out, void InitializeKeyboard(
Core::Frontend::SoftwareKeyboardParameters parameters) const override; bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
void SendTextCheckDialog(std::u16string error_message, std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
std::function<void()> finished_check_) const override; 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: signals:
void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const; void MainWindowInitializeKeyboard(
void MainWindowTextCheckDialog(std::u16string error_message) const; 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: private:
void MainWindowFinishedText(std::optional<std::u16string> text); void SubmitNormalText(Service::AM::Applets::SwkbdResult result,
void MainWindowFinishedCheckDialog(); std::u16string submitted_text) const;
mutable std::function<void(std::optional<std::u16string>)> text_output; void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
mutable std::function<void()> finished_check; 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;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -101,6 +101,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "core/perf_stats.h" #include "core/perf_stats.h"
#include "core/telemetry_session.h" #include "core/telemetry_session.h"
#include "input_common/main.h" #include "input_common/main.h"
#include "util/overlay_dialog.h"
#include "video_core/gpu.h" #include "video_core/gpu.h"
#include "video_core/shader_notify.h" #include "video_core/shader_notify.h"
#include "yuzu/about_dialog.h" #include "yuzu/about_dialog.h"
@ -227,6 +228,8 @@ GMainWindow::GMainWindow()
SetDiscordEnabled(UISettings::values.enable_discord_presence); SetDiscordEnabled(UISettings::values.enable_discord_presence);
discord_rpc->Update(); discord_rpc->Update();
RegisterMetaTypes();
InitializeWidgets(); InitializeWidgets();
InitializeDebugWidgets(); InitializeDebugWidgets();
InitializeRecentFileMenuActions(); InitializeRecentFileMenuActions();
@ -375,6 +378,55 @@ GMainWindow::~GMainWindow() {
delete render_window; 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( void GMainWindow::ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters) { const Core::Frontend::ControllerParameters& parameters) {
QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get());
@ -414,25 +466,112 @@ void GMainWindow::ProfileSelectorSelectProfile() {
emit ProfileSelectorFinishedSelection(uuid); emit ProfileSelectorFinishedSelection(uuid);
} }
void GMainWindow::SoftwareKeyboardGetText( void GMainWindow::SoftwareKeyboardInitialize(
const Core::Frontend::SoftwareKeyboardParameters& parameters) { bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) {
QtSoftwareKeyboardDialog dialog(this, parameters); if (software_keyboard) {
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | LOG_ERROR(Frontend, "The software keyboard is already initialized!");
Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
Qt::WindowCloseButtonHint);
dialog.setWindowModality(Qt::WindowModal);
if (dialog.exec() == QDialog::Rejected) {
emit SoftwareKeyboardFinishedText(std::nullopt);
return; 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) { void GMainWindow::SoftwareKeyboardShowNormal() {
QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message)); if (!software_keyboard) {
emit SoftwareKeyboardFinishedCheckDialog(); 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, 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, connect(this, &GMainWindow::EmulationStopping, render_window,
&GRenderWindow::OnEmulationStopping); &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); connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar);
} }
@ -2187,15 +2330,6 @@ void GMainWindow::OnStartGame() {
emu_thread->SetRunning(true); 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); connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
ui.action_Start->setEnabled(false); ui.action_Start->setEnabled(false);
@ -2244,8 +2378,11 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
BootGame(last_filename_booted, program_index); BootGame(last_filename_booted, program_index);
} }
void GMainWindow::ErrorDisplayDisplayError(QString body) { void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
QMessageBox::critical(this, tr("Error Display"), body); OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text,
QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter);
dialog.exec();
emit ErrorDisplayFinished(); emit ErrorDisplayFinished();
} }

View File

@ -37,9 +37,13 @@ enum class GameListRemoveTarget;
enum class InstalledEntryType; enum class InstalledEntryType;
class GameListPlaceholder; class GameListPlaceholder;
class QtSoftwareKeyboardDialog;
namespace Core::Frontend { namespace Core::Frontend {
struct ControllerParameters; struct ControllerParameters;
struct SoftwareKeyboardParameters; struct InlineAppearParameters;
struct InlineTextParameters;
struct KeyboardInitializeParameters;
} // namespace Core::Frontend } // namespace Core::Frontend
namespace DiscordRPC { namespace DiscordRPC {
@ -57,8 +61,11 @@ class InputSubsystem;
} }
namespace Service::AM::Applets { namespace Service::AM::Applets {
enum class SwkbdResult : u32;
enum class SwkbdTextCheckResult : u32;
enum class SwkbdReplyType : u32;
enum class WebExitReason : u32; enum class WebExitReason : u32;
} } // namespace Service::AM::Applets
enum class EmulatedDirectoryTarget { enum class EmulatedDirectoryTarget {
NAND, NAND,
@ -128,8 +135,10 @@ signals:
void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid);
void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); void SoftwareKeyboardSubmitNormalText(Service::AM::Applets::SwkbdResult result,
void SoftwareKeyboardFinishedCheckDialog(); std::u16string submitted_text);
void SoftwareKeyboardSubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
std::u16string submitted_text, s32 cursor_position);
void WebBrowserExtractOfflineRomFS(); void WebBrowserExtractOfflineRomFS();
void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); 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 OnExecuteProgram(std::size_t program_index);
void ControllerSelectorReconfigureControllers( void ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters); 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 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, void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
bool is_local); bool is_local);
void OnAppFocusStateChanged(Qt::ApplicationState state); void OnAppFocusStateChanged(Qt::ApplicationState state);
private: private:
void RegisterMetaTypes();
void InitializeWidgets(); void InitializeWidgets();
void InitializeDebugWidgets(); void InitializeDebugWidgets();
void InitializeRecentFileMenuActions(); void InitializeRecentFileMenuActions();
@ -334,6 +352,9 @@ private:
// Disables the web applet for the rest of the emulated session // Disables the web applet for the rest of the emulated session
bool disable_web_applet{}; bool disable_web_applet{};
// Applets
QtSoftwareKeyboardDialog* software_keyboard = nullptr;
protected: protected:
void dropEvent(QDropEvent* event) override; void dropEvent(QDropEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override;

View File

@ -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));
}
}

View File

@ -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{};
};

View File

@ -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>