| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | // Copyright 2021 yuzu Emulator Project
 | 
					
						
							| 
									
										
										
										
											2018-11-09 20:13:15 -05:00
										 |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | #include <QCursor>
 | 
					
						
							|  |  |  | #include <QKeyEvent>
 | 
					
						
							|  |  |  | #include <QScreen>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "common/logging/log.h"
 | 
					
						
							|  |  |  | #include "common/settings.h"
 | 
					
						
							|  |  |  | #include "common/string_util.h"
 | 
					
						
							|  |  |  | #include "core/core.h"
 | 
					
						
							|  |  |  | #include "core/frontend/input_interpreter.h"
 | 
					
						
							| 
									
										
										
										
											2021-07-14 00:29:12 -04:00
										 |  |  | #include "ui_qt_software_keyboard.h"
 | 
					
						
							|  |  |  | #include "yuzu/applets/qt_software_keyboard.h"
 | 
					
						
							| 
									
										
										
										
											2018-11-11 16:39:25 -05:00
										 |  |  | #include "yuzu/main.h"
 | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | #include "yuzu/util/overlay_dialog.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace Service::AM::Applets; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | constexpr float BASE_HEADER_FONT_SIZE = 23.0f; | 
					
						
							|  |  |  | constexpr float BASE_SUB_FONT_SIZE = 17.0f; | 
					
						
							|  |  |  | constexpr float BASE_EDITOR_FONT_SIZE = 26.0f; | 
					
						
							|  |  |  | constexpr float BASE_CHAR_BUTTON_FONT_SIZE = 28.0f; | 
					
						
							|  |  |  | constexpr float BASE_LABEL_BUTTON_FONT_SIZE = 18.0f; | 
					
						
							|  |  |  | constexpr float BASE_ICON_BUTTON_SIZE = 36.0f; | 
					
						
							|  |  |  | [[maybe_unused]] constexpr float BASE_WIDTH = 1280.0f; | 
					
						
							|  |  |  | constexpr float BASE_HEIGHT = 720.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // Anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( | 
					
						
							|  |  |  |     QWidget* parent, Core::System& system_, bool is_inline_, | 
					
						
							|  |  |  |     Core::Frontend::KeyboardInitializeParameters initialize_parameters_) | 
					
						
							|  |  |  |     : QDialog(parent), ui{std::make_unique<Ui::QtSoftwareKeyboardDialog>()}, system{system_}, | 
					
						
							|  |  |  |       is_inline{is_inline_}, initialize_parameters{std::move(initialize_parameters_)} { | 
					
						
							|  |  |  |     ui->setupUi(this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint | | 
					
						
							|  |  |  |                    Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint); | 
					
						
							|  |  |  |     setWindowModality(Qt::WindowModal); | 
					
						
							|  |  |  |     setAttribute(Qt::WA_DeleteOnClose); | 
					
						
							|  |  |  |     setAttribute(Qt::WA_TranslucentBackground); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     keyboard_buttons = {{ | 
					
						
							|  |  |  |         {{ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_1, | 
					
						
							|  |  |  |                 ui->button_2, | 
					
						
							|  |  |  |                 ui->button_3, | 
					
						
							|  |  |  |                 ui->button_4, | 
					
						
							|  |  |  |                 ui->button_5, | 
					
						
							|  |  |  |                 ui->button_6, | 
					
						
							|  |  |  |                 ui->button_7, | 
					
						
							|  |  |  |                 ui->button_8, | 
					
						
							|  |  |  |                 ui->button_9, | 
					
						
							|  |  |  |                 ui->button_0, | 
					
						
							|  |  |  |                 ui->button_minus, | 
					
						
							|  |  |  |                 ui->button_backspace, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_q, | 
					
						
							|  |  |  |                 ui->button_w, | 
					
						
							|  |  |  |                 ui->button_e, | 
					
						
							|  |  |  |                 ui->button_r, | 
					
						
							|  |  |  |                 ui->button_t, | 
					
						
							|  |  |  |                 ui->button_y, | 
					
						
							|  |  |  |                 ui->button_u, | 
					
						
							|  |  |  |                 ui->button_i, | 
					
						
							|  |  |  |                 ui->button_o, | 
					
						
							|  |  |  |                 ui->button_p, | 
					
						
							|  |  |  |                 ui->button_slash, | 
					
						
							|  |  |  |                 ui->button_return, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_a, | 
					
						
							|  |  |  |                 ui->button_s, | 
					
						
							|  |  |  |                 ui->button_d, | 
					
						
							|  |  |  |                 ui->button_f, | 
					
						
							|  |  |  |                 ui->button_g, | 
					
						
							|  |  |  |                 ui->button_h, | 
					
						
							|  |  |  |                 ui->button_j, | 
					
						
							|  |  |  |                 ui->button_k, | 
					
						
							|  |  |  |                 ui->button_l, | 
					
						
							|  |  |  |                 ui->button_colon, | 
					
						
							|  |  |  |                 ui->button_apostrophe, | 
					
						
							|  |  |  |                 ui->button_return, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_z, | 
					
						
							|  |  |  |                 ui->button_x, | 
					
						
							|  |  |  |                 ui->button_c, | 
					
						
							|  |  |  |                 ui->button_v, | 
					
						
							|  |  |  |                 ui->button_b, | 
					
						
							|  |  |  |                 ui->button_n, | 
					
						
							|  |  |  |                 ui->button_m, | 
					
						
							|  |  |  |                 ui->button_comma, | 
					
						
							|  |  |  |                 ui->button_dot, | 
					
						
							|  |  |  |                 ui->button_question, | 
					
						
							|  |  |  |                 ui->button_exclamation, | 
					
						
							|  |  |  |                 ui->button_ok, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_shift, | 
					
						
							|  |  |  |                 ui->button_shift, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_space, | 
					
						
							|  |  |  |                 ui->button_ok, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }}, | 
					
						
							|  |  |  |         {{ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_hash, | 
					
						
							|  |  |  |                 ui->button_left_bracket, | 
					
						
							|  |  |  |                 ui->button_right_bracket, | 
					
						
							|  |  |  |                 ui->button_dollar, | 
					
						
							|  |  |  |                 ui->button_percent, | 
					
						
							|  |  |  |                 ui->button_circumflex, | 
					
						
							|  |  |  |                 ui->button_ampersand, | 
					
						
							|  |  |  |                 ui->button_asterisk, | 
					
						
							|  |  |  |                 ui->button_left_parenthesis, | 
					
						
							|  |  |  |                 ui->button_right_parenthesis, | 
					
						
							|  |  |  |                 ui->button_underscore, | 
					
						
							|  |  |  |                 ui->button_backspace_shift, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_q_shift, | 
					
						
							|  |  |  |                 ui->button_w_shift, | 
					
						
							|  |  |  |                 ui->button_e_shift, | 
					
						
							|  |  |  |                 ui->button_r_shift, | 
					
						
							|  |  |  |                 ui->button_t_shift, | 
					
						
							|  |  |  |                 ui->button_y_shift, | 
					
						
							|  |  |  |                 ui->button_u_shift, | 
					
						
							|  |  |  |                 ui->button_i_shift, | 
					
						
							|  |  |  |                 ui->button_o_shift, | 
					
						
							|  |  |  |                 ui->button_p_shift, | 
					
						
							|  |  |  |                 ui->button_at, | 
					
						
							|  |  |  |                 ui->button_return_shift, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_a_shift, | 
					
						
							|  |  |  |                 ui->button_s_shift, | 
					
						
							|  |  |  |                 ui->button_d_shift, | 
					
						
							|  |  |  |                 ui->button_f_shift, | 
					
						
							|  |  |  |                 ui->button_g_shift, | 
					
						
							|  |  |  |                 ui->button_h_shift, | 
					
						
							|  |  |  |                 ui->button_j_shift, | 
					
						
							|  |  |  |                 ui->button_k_shift, | 
					
						
							|  |  |  |                 ui->button_l_shift, | 
					
						
							|  |  |  |                 ui->button_semicolon, | 
					
						
							|  |  |  |                 ui->button_quotation, | 
					
						
							|  |  |  |                 ui->button_return_shift, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_z_shift, | 
					
						
							|  |  |  |                 ui->button_x_shift, | 
					
						
							|  |  |  |                 ui->button_c_shift, | 
					
						
							|  |  |  |                 ui->button_v_shift, | 
					
						
							|  |  |  |                 ui->button_b_shift, | 
					
						
							|  |  |  |                 ui->button_n_shift, | 
					
						
							|  |  |  |                 ui->button_m_shift, | 
					
						
							|  |  |  |                 ui->button_less_than, | 
					
						
							|  |  |  |                 ui->button_greater_than, | 
					
						
							|  |  |  |                 ui->button_plus, | 
					
						
							|  |  |  |                 ui->button_equal, | 
					
						
							|  |  |  |                 ui->button_ok_shift, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ui->button_shift_shift, | 
					
						
							|  |  |  |                 ui->button_shift_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_space_shift, | 
					
						
							|  |  |  |                 ui->button_ok_shift, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }}, | 
					
						
							|  |  |  |     }}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     numberpad_buttons = {{ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ui->button_1_num, | 
					
						
							|  |  |  |             ui->button_2_num, | 
					
						
							|  |  |  |             ui->button_3_num, | 
					
						
							|  |  |  |             ui->button_backspace_num, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ui->button_4_num, | 
					
						
							|  |  |  |             ui->button_5_num, | 
					
						
							|  |  |  |             ui->button_6_num, | 
					
						
							|  |  |  |             ui->button_ok_num, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ui->button_7_num, | 
					
						
							|  |  |  |             ui->button_8_num, | 
					
						
							|  |  |  |             ui->button_9_num, | 
					
						
							|  |  |  |             ui->button_ok_num, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             nullptr, | 
					
						
							|  |  |  |             ui->button_0_num, | 
					
						
							|  |  |  |             nullptr, | 
					
						
							|  |  |  |             ui->button_ok_num, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     }}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     all_buttons = { | 
					
						
							|  |  |  |         ui->button_1, | 
					
						
							|  |  |  |         ui->button_2, | 
					
						
							|  |  |  |         ui->button_3, | 
					
						
							|  |  |  |         ui->button_4, | 
					
						
							|  |  |  |         ui->button_5, | 
					
						
							|  |  |  |         ui->button_6, | 
					
						
							|  |  |  |         ui->button_7, | 
					
						
							|  |  |  |         ui->button_8, | 
					
						
							|  |  |  |         ui->button_9, | 
					
						
							|  |  |  |         ui->button_0, | 
					
						
							|  |  |  |         ui->button_minus, | 
					
						
							|  |  |  |         ui->button_backspace, | 
					
						
							|  |  |  |         ui->button_q, | 
					
						
							|  |  |  |         ui->button_w, | 
					
						
							|  |  |  |         ui->button_e, | 
					
						
							|  |  |  |         ui->button_r, | 
					
						
							|  |  |  |         ui->button_t, | 
					
						
							|  |  |  |         ui->button_y, | 
					
						
							|  |  |  |         ui->button_u, | 
					
						
							|  |  |  |         ui->button_i, | 
					
						
							|  |  |  |         ui->button_o, | 
					
						
							|  |  |  |         ui->button_p, | 
					
						
							|  |  |  |         ui->button_slash, | 
					
						
							|  |  |  |         ui->button_return, | 
					
						
							|  |  |  |         ui->button_a, | 
					
						
							|  |  |  |         ui->button_s, | 
					
						
							|  |  |  |         ui->button_d, | 
					
						
							|  |  |  |         ui->button_f, | 
					
						
							|  |  |  |         ui->button_g, | 
					
						
							|  |  |  |         ui->button_h, | 
					
						
							|  |  |  |         ui->button_j, | 
					
						
							|  |  |  |         ui->button_k, | 
					
						
							|  |  |  |         ui->button_l, | 
					
						
							|  |  |  |         ui->button_colon, | 
					
						
							|  |  |  |         ui->button_apostrophe, | 
					
						
							|  |  |  |         ui->button_z, | 
					
						
							|  |  |  |         ui->button_x, | 
					
						
							|  |  |  |         ui->button_c, | 
					
						
							|  |  |  |         ui->button_v, | 
					
						
							|  |  |  |         ui->button_b, | 
					
						
							|  |  |  |         ui->button_n, | 
					
						
							|  |  |  |         ui->button_m, | 
					
						
							|  |  |  |         ui->button_comma, | 
					
						
							|  |  |  |         ui->button_dot, | 
					
						
							|  |  |  |         ui->button_question, | 
					
						
							|  |  |  |         ui->button_exclamation, | 
					
						
							|  |  |  |         ui->button_ok, | 
					
						
							|  |  |  |         ui->button_shift, | 
					
						
							|  |  |  |         ui->button_space, | 
					
						
							|  |  |  |         ui->button_hash, | 
					
						
							|  |  |  |         ui->button_left_bracket, | 
					
						
							|  |  |  |         ui->button_right_bracket, | 
					
						
							|  |  |  |         ui->button_dollar, | 
					
						
							|  |  |  |         ui->button_percent, | 
					
						
							|  |  |  |         ui->button_circumflex, | 
					
						
							|  |  |  |         ui->button_ampersand, | 
					
						
							|  |  |  |         ui->button_asterisk, | 
					
						
							|  |  |  |         ui->button_left_parenthesis, | 
					
						
							|  |  |  |         ui->button_right_parenthesis, | 
					
						
							|  |  |  |         ui->button_underscore, | 
					
						
							|  |  |  |         ui->button_backspace_shift, | 
					
						
							|  |  |  |         ui->button_q_shift, | 
					
						
							|  |  |  |         ui->button_w_shift, | 
					
						
							|  |  |  |         ui->button_e_shift, | 
					
						
							|  |  |  |         ui->button_r_shift, | 
					
						
							|  |  |  |         ui->button_t_shift, | 
					
						
							|  |  |  |         ui->button_y_shift, | 
					
						
							|  |  |  |         ui->button_u_shift, | 
					
						
							|  |  |  |         ui->button_i_shift, | 
					
						
							|  |  |  |         ui->button_o_shift, | 
					
						
							|  |  |  |         ui->button_p_shift, | 
					
						
							|  |  |  |         ui->button_at, | 
					
						
							|  |  |  |         ui->button_return_shift, | 
					
						
							|  |  |  |         ui->button_a_shift, | 
					
						
							|  |  |  |         ui->button_s_shift, | 
					
						
							|  |  |  |         ui->button_d_shift, | 
					
						
							|  |  |  |         ui->button_f_shift, | 
					
						
							|  |  |  |         ui->button_g_shift, | 
					
						
							|  |  |  |         ui->button_h_shift, | 
					
						
							|  |  |  |         ui->button_j_shift, | 
					
						
							|  |  |  |         ui->button_k_shift, | 
					
						
							|  |  |  |         ui->button_l_shift, | 
					
						
							|  |  |  |         ui->button_semicolon, | 
					
						
							|  |  |  |         ui->button_quotation, | 
					
						
							|  |  |  |         ui->button_z_shift, | 
					
						
							|  |  |  |         ui->button_x_shift, | 
					
						
							|  |  |  |         ui->button_c_shift, | 
					
						
							|  |  |  |         ui->button_v_shift, | 
					
						
							|  |  |  |         ui->button_b_shift, | 
					
						
							|  |  |  |         ui->button_n_shift, | 
					
						
							|  |  |  |         ui->button_m_shift, | 
					
						
							|  |  |  |         ui->button_less_than, | 
					
						
							|  |  |  |         ui->button_greater_than, | 
					
						
							|  |  |  |         ui->button_plus, | 
					
						
							|  |  |  |         ui->button_equal, | 
					
						
							|  |  |  |         ui->button_ok_shift, | 
					
						
							|  |  |  |         ui->button_shift_shift, | 
					
						
							|  |  |  |         ui->button_space_shift, | 
					
						
							|  |  |  |         ui->button_1_num, | 
					
						
							|  |  |  |         ui->button_2_num, | 
					
						
							|  |  |  |         ui->button_3_num, | 
					
						
							|  |  |  |         ui->button_backspace_num, | 
					
						
							|  |  |  |         ui->button_4_num, | 
					
						
							|  |  |  |         ui->button_5_num, | 
					
						
							|  |  |  |         ui->button_6_num, | 
					
						
							|  |  |  |         ui->button_ok_num, | 
					
						
							|  |  |  |         ui->button_7_num, | 
					
						
							|  |  |  |         ui->button_8_num, | 
					
						
							|  |  |  |         ui->button_9_num, | 
					
						
							|  |  |  |         ui->button_0_num, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SetupMouseHover(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!initialize_parameters.ok_text.empty()) { | 
					
						
							|  |  |  |         ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text)); | 
					
						
							|  |  |  |     ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     current_text = initialize_parameters.initial_text; | 
					
						
							|  |  |  |     cursor_position = initialize_parameters.initial_cursor_position; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SetTextDrawType(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto* button : all_buttons) { | 
					
						
							|  |  |  |         connect(button, &QPushButton::clicked, this, [this, button](bool) { | 
					
						
							|  |  |  |             if (is_inline) { | 
					
						
							|  |  |  |                 InlineKeyboardButtonClicked(button); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 NormalKeyboardButtonClicked(button); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
 | 
					
						
							|  |  |  |     if (system.IsPoweredOn()) { | 
					
						
							|  |  |  |         input_interpreter = std::make_unique<InputInterpreter>(system); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() { | 
					
						
							|  |  |  |     StopInputThread(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) { | 
					
						
							|  |  |  |     if (isVisible()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     MoveAndResizeWindow(pos, size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SetKeyboardType(); | 
					
						
							|  |  |  |     SetPasswordMode(); | 
					
						
							|  |  |  |     SetControllerImage(); | 
					
						
							|  |  |  |     DisableKeyboardButtons(); | 
					
						
							|  |  |  |     SetBackspaceOkEnabled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     open(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::ShowTextCheckDialog( | 
					
						
							|  |  |  |     Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 
					
						
							|  |  |  |     std::u16string text_check_message) { | 
					
						
							|  |  |  |     switch (text_check_result) { | 
					
						
							|  |  |  |     case SwkbdTextCheckResult::Success: | 
					
						
							|  |  |  |     case SwkbdTextCheckResult::Silent: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SwkbdTextCheckResult::Failure: { | 
					
						
							|  |  |  |         StopInputThread(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), | 
					
						
							|  |  |  |                              QString{}, tr("OK"), Qt::AlignCenter); | 
					
						
							|  |  |  |         dialog.exec(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         StartInputThread(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SwkbdTextCheckResult::Confirm: { | 
					
						
							|  |  |  |         StopInputThread(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), | 
					
						
							|  |  |  |                              tr("Cancel"), tr("OK"), Qt::AlignCenter); | 
					
						
							| 
									
										
										
										
											2021-05-18 08:20:05 -04:00
										 |  |  |         if (dialog.exec() != QDialog::Accepted) { | 
					
						
							|  |  |  |             StartInputThread(); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-18 08:20:05 -04:00
										 |  |  |         auto text = ui->topOSK->currentIndex() == 1 | 
					
						
							|  |  |  |                         ? ui->text_edit_osk->toPlainText().toStdU16String() | 
					
						
							|  |  |  |                         : ui->line_edit_osk->text().toStdU16String(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         emit SubmitNormalText(SwkbdResult::Ok, std::move(text)); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::ShowInlineKeyboard( | 
					
						
							|  |  |  |     Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, QSize size) { | 
					
						
							|  |  |  |     MoveAndResizeWindow(pos, size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->topOSK->setStyleSheet(QStringLiteral("background: rgba(0, 0, 0, 0);")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->headerOSK->hide(); | 
					
						
							|  |  |  |     ui->subOSK->hide(); | 
					
						
							|  |  |  |     ui->inputOSK->hide(); | 
					
						
							|  |  |  |     ui->charactersOSK->hide(); | 
					
						
							|  |  |  |     ui->inputBoxOSK->hide(); | 
					
						
							|  |  |  |     ui->charactersBoxOSK->hide(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     initialize_parameters.max_text_length = appear_parameters.max_text_length; | 
					
						
							|  |  |  |     initialize_parameters.min_text_length = appear_parameters.min_text_length; | 
					
						
							|  |  |  |     initialize_parameters.type = appear_parameters.type; | 
					
						
							|  |  |  |     initialize_parameters.key_disable_flags = appear_parameters.key_disable_flags; | 
					
						
							|  |  |  |     initialize_parameters.enable_backspace_button = appear_parameters.enable_backspace_button; | 
					
						
							|  |  |  |     initialize_parameters.enable_return_button = appear_parameters.enable_return_button; | 
					
						
							| 
									
										
										
										
											2021-08-19 22:17:15 +03:00
										 |  |  |     initialize_parameters.disable_cancel_button = appear_parameters.disable_cancel_button; | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     SetKeyboardType(); | 
					
						
							|  |  |  |     SetControllerImage(); | 
					
						
							|  |  |  |     DisableKeyboardButtons(); | 
					
						
							|  |  |  |     SetBackspaceOkEnabled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     open(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::HideInlineKeyboard() { | 
					
						
							|  |  |  |     StopInputThread(); | 
					
						
							|  |  |  |     QDialog::hide(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::InlineTextChanged( | 
					
						
							|  |  |  |     Core::Frontend::InlineTextParameters text_parameters) { | 
					
						
							|  |  |  |     current_text = text_parameters.input_text; | 
					
						
							|  |  |  |     cursor_position = text_parameters.cursor_position; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SetBackspaceOkEnabled(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::ExitKeyboard() { | 
					
						
							|  |  |  |     StopInputThread(); | 
					
						
							|  |  |  |     QDialog::done(QDialog::Accepted); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::open() { | 
					
						
							|  |  |  |     QDialog::open(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     row = 0; | 
					
						
							|  |  |  |     column = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto* const curr_button = | 
					
						
							|  |  |  |         keyboard_buttons[static_cast<int>(bottom_osk_index)][row][column]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // This is a workaround for setFocus() randomly not showing focus in the UI
 | 
					
						
							|  |  |  |     QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     StartInputThread(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::reject() { | 
					
						
							|  |  |  |     // Pressing the ESC key in a dialog calls QDialog::reject().
 | 
					
						
							|  |  |  |     // We will override this behavior to the "Cancel" action on the software keyboard.
 | 
					
						
							| 
									
										
										
										
											2021-05-18 08:20:05 -04:00
										 |  |  |     TranslateButtonPress(HIDButton::X); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { | 
					
						
							|  |  |  |     if (!is_inline) { | 
					
						
							|  |  |  |         QDialog::keyPressEvent(event); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto entered_key = event->key(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (entered_key) { | 
					
						
							|  |  |  |     case Qt::Key_Escape: | 
					
						
							|  |  |  |         QDialog::keyPressEvent(event); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     case Qt::Key_Backspace: | 
					
						
							|  |  |  |         switch (bottom_osk_index) { | 
					
						
							|  |  |  |         case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |             ui->button_backspace->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |             ui->button_backspace_shift->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::NumberPad: | 
					
						
							|  |  |  |             ui->button_backspace_num->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     case Qt::Key_Return: | 
					
						
							|  |  |  |         switch (bottom_osk_index) { | 
					
						
							|  |  |  |         case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |             ui->button_ok->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |             ui->button_ok_shift->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::NumberPad: | 
					
						
							|  |  |  |             ui->button_ok_num->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     case Qt::Key_Left: | 
					
						
							|  |  |  |         MoveTextCursorDirection(Direction::Left); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     case Qt::Key_Right: | 
					
						
							|  |  |  |         MoveTextCursorDirection(Direction::Right); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto entered_text = event->text(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (entered_text.isEmpty()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InlineTextInsertString(entered_text.toStdU16String()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) { | 
					
						
							|  |  |  |     QDialog::move(pos); | 
					
						
							|  |  |  |     QDialog::resize(size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // High DPI
 | 
					
						
							|  |  |  |     const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     RescaleKeyboardElements(size.width(), size.height(), dpi_scale); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::RescaleKeyboardElements(float width, float height, float dpi_scale) { | 
					
						
							|  |  |  |     const auto header_font_size = BASE_HEADER_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; | 
					
						
							|  |  |  |     const auto sub_font_size = BASE_SUB_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; | 
					
						
							|  |  |  |     const auto editor_font_size = BASE_EDITOR_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; | 
					
						
							|  |  |  |     const auto char_button_font_size = | 
					
						
							|  |  |  |         BASE_CHAR_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; | 
					
						
							|  |  |  |     const auto label_button_font_size = | 
					
						
							|  |  |  |         BASE_LABEL_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QFont header_font(QStringLiteral("MS Shell Dlg 2"), header_font_size, QFont::Normal); | 
					
						
							|  |  |  |     QFont sub_font(QStringLiteral("MS Shell Dlg 2"), sub_font_size, QFont::Normal); | 
					
						
							|  |  |  |     QFont editor_font(QStringLiteral("MS Shell Dlg 2"), editor_font_size, QFont::Normal); | 
					
						
							|  |  |  |     QFont char_button_font(QStringLiteral("MS Shell Dlg 2"), char_button_font_size, QFont::Normal); | 
					
						
							|  |  |  |     QFont label_button_font(QStringLiteral("MS Shell Dlg 2"), label_button_font_size, | 
					
						
							|  |  |  |                             QFont::Normal); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->label_header->setFont(header_font); | 
					
						
							|  |  |  |     ui->label_sub->setFont(sub_font); | 
					
						
							|  |  |  |     ui->line_edit_osk->setFont(editor_font); | 
					
						
							|  |  |  |     ui->text_edit_osk->setFont(editor_font); | 
					
						
							|  |  |  |     ui->label_characters->setFont(sub_font); | 
					
						
							|  |  |  |     ui->label_characters_box->setFont(sub_font); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->label_shift->setFont(label_button_font); | 
					
						
							|  |  |  |     ui->label_shift_shift->setFont(label_button_font); | 
					
						
							|  |  |  |     ui->label_cancel->setFont(label_button_font); | 
					
						
							|  |  |  |     ui->label_cancel_shift->setFont(label_button_font); | 
					
						
							|  |  |  |     ui->label_cancel_num->setFont(label_button_font); | 
					
						
							|  |  |  |     ui->label_enter->setFont(label_button_font); | 
					
						
							|  |  |  |     ui->label_enter_shift->setFont(label_button_font); | 
					
						
							|  |  |  |     ui->label_enter_num->setFont(label_button_font); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto* button : all_buttons) { | 
					
						
							|  |  |  |         if (button == ui->button_return || button == ui->button_return_shift) { | 
					
						
							|  |  |  |             button->setFont(label_button_font); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (button == ui->button_space || button == ui->button_space_shift) { | 
					
						
							|  |  |  |             button->setFont(label_button_font); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (button == ui->button_shift || button == ui->button_shift_shift) { | 
					
						
							|  |  |  |             button->setFont(label_button_font); | 
					
						
							|  |  |  |             button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) * | 
					
						
							|  |  |  |                                 (height / BASE_HEIGHT)); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (button == ui->button_backspace || button == ui->button_backspace_shift || | 
					
						
							|  |  |  |             button == ui->button_backspace_num) { | 
					
						
							|  |  |  |             button->setFont(label_button_font); | 
					
						
							|  |  |  |             button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) * | 
					
						
							|  |  |  |                                 (height / BASE_HEIGHT)); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (button == ui->button_ok || button == ui->button_ok_shift || | 
					
						
							|  |  |  |             button == ui->button_ok_num) { | 
					
						
							|  |  |  |             button->setFont(label_button_font); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         button->setFont(char_button_font); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::SetKeyboardType() { | 
					
						
							|  |  |  |     switch (initialize_parameters.type) { | 
					
						
							|  |  |  |     case SwkbdType::Normal: | 
					
						
							|  |  |  |     case SwkbdType::Qwerty: | 
					
						
							|  |  |  |     case SwkbdType::Unknown3: | 
					
						
							|  |  |  |     case SwkbdType::Latin: | 
					
						
							|  |  |  |     case SwkbdType::SimplifiedChinese: | 
					
						
							|  |  |  |     case SwkbdType::TraditionalChinese: | 
					
						
							|  |  |  |     case SwkbdType::Korean: | 
					
						
							|  |  |  |     default: { | 
					
						
							|  |  |  |         bottom_osk_index = BottomOSKIndex::LowerCase; | 
					
						
							|  |  |  |         ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->verticalLayout_2->setStretch(0, 320); | 
					
						
							|  |  |  |         ui->verticalLayout_2->setStretch(1, 400); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->gridLineOSK->setRowStretch(5, 94); | 
					
						
							|  |  |  |         ui->gridBoxOSK->setRowStretch(2, 81); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SwkbdType::NumberPad: { | 
					
						
							|  |  |  |         bottom_osk_index = BottomOSKIndex::NumberPad; | 
					
						
							|  |  |  |         ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->verticalLayout_2->setStretch(0, 370); | 
					
						
							|  |  |  |         ui->verticalLayout_2->setStretch(1, 350); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->gridLineOSK->setRowStretch(5, 144); | 
					
						
							|  |  |  |         ui->gridBoxOSK->setRowStretch(2, 131); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::SetPasswordMode() { | 
					
						
							|  |  |  |     switch (initialize_parameters.password_mode) { | 
					
						
							|  |  |  |     case SwkbdPasswordMode::Disabled: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         ui->line_edit_osk->setEchoMode(QLineEdit::Normal); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SwkbdPasswordMode::Enabled: | 
					
						
							|  |  |  |         ui->line_edit_osk->setEchoMode(QLineEdit::Password); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::SetTextDrawType() { | 
					
						
							|  |  |  |     switch (initialize_parameters.text_draw_type) { | 
					
						
							|  |  |  |     case SwkbdTextDrawType::Line: | 
					
						
							|  |  |  |     case SwkbdTextDrawType::DownloadCode: { | 
					
						
							|  |  |  |         ui->topOSK->setCurrentIndex(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (initialize_parameters.max_text_length <= 10) { | 
					
						
							|  |  |  |             ui->gridLineOSK->setColumnStretch(0, 390); | 
					
						
							|  |  |  |             ui->gridLineOSK->setColumnStretch(1, 500); | 
					
						
							|  |  |  |             ui->gridLineOSK->setColumnStretch(2, 390); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ui->gridLineOSK->setColumnStretch(0, 130); | 
					
						
							|  |  |  |             ui->gridLineOSK->setColumnStretch(1, 1020); | 
					
						
							|  |  |  |             ui->gridLineOSK->setColumnStretch(2, 130); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_inline) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         connect(ui->line_edit_osk, &QLineEdit::textChanged, [this](const QString& changed_string) { | 
					
						
							|  |  |  |             const auto is_valid = ValidateInputText(changed_string); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const auto text_length = static_cast<u32>(changed_string.length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->label_characters->setText(QStringLiteral("%1/%2") | 
					
						
							|  |  |  |                                               .arg(text_length) | 
					
						
							|  |  |  |                                               .arg(initialize_parameters.max_text_length)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->button_ok->setEnabled(is_valid); | 
					
						
							|  |  |  |             ui->button_ok_shift->setEnabled(is_valid); | 
					
						
							|  |  |  |             ui->button_ok_num->setEnabled(is_valid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->line_edit_osk->setFocus(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         connect(ui->line_edit_osk, &QLineEdit::cursorPositionChanged, | 
					
						
							|  |  |  |                 [this](int old_cursor_position, int new_cursor_position) { | 
					
						
							|  |  |  |                     ui->button_backspace->setEnabled( | 
					
						
							|  |  |  |                         initialize_parameters.enable_backspace_button && new_cursor_position > 0); | 
					
						
							|  |  |  |                     ui->button_backspace_shift->setEnabled( | 
					
						
							|  |  |  |                         initialize_parameters.enable_backspace_button && new_cursor_position > 0); | 
					
						
							|  |  |  |                     ui->button_backspace_num->setEnabled( | 
					
						
							|  |  |  |                         initialize_parameters.enable_backspace_button && new_cursor_position > 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     ui->line_edit_osk->setFocus(); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-18 22:21:46 -04:00
										 |  |  |         connect( | 
					
						
							|  |  |  |             ui->line_edit_osk, &QLineEdit::returnPressed, this, | 
					
						
							|  |  |  |             [this] { TranslateButtonPress(HIDButton::Plus); }, Qt::QueuedConnection); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ui->line_edit_osk->setPlaceholderText( | 
					
						
							|  |  |  |             QString::fromStdU16String(initialize_parameters.guide_text)); | 
					
						
							|  |  |  |         ui->line_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text)); | 
					
						
							|  |  |  |         ui->line_edit_osk->setMaxLength(initialize_parameters.max_text_length); | 
					
						
							|  |  |  |         ui->line_edit_osk->setCursorPosition(initialize_parameters.initial_cursor_position); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->label_characters->setText(QStringLiteral("%1/%2") | 
					
						
							|  |  |  |                                           .arg(initialize_parameters.initial_text.size()) | 
					
						
							|  |  |  |                                           .arg(initialize_parameters.max_text_length)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SwkbdTextDrawType::Box: | 
					
						
							|  |  |  |     default: { | 
					
						
							|  |  |  |         ui->topOSK->setCurrentIndex(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_inline) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         connect(ui->text_edit_osk, &QTextEdit::textChanged, [this] { | 
					
						
							|  |  |  |             if (static_cast<u32>(ui->text_edit_osk->toPlainText().length()) > | 
					
						
							|  |  |  |                 initialize_parameters.max_text_length) { | 
					
						
							|  |  |  |                 auto text_cursor = ui->text_edit_osk->textCursor(); | 
					
						
							|  |  |  |                 ui->text_edit_osk->setTextCursor(text_cursor); | 
					
						
							|  |  |  |                 text_cursor.deletePreviousChar(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const auto is_valid = ValidateInputText(ui->text_edit_osk->toPlainText()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const auto text_length = static_cast<u32>(ui->text_edit_osk->toPlainText().length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->label_characters_box->setText(QStringLiteral("%1/%2") | 
					
						
							|  |  |  |                                                   .arg(text_length) | 
					
						
							|  |  |  |                                                   .arg(initialize_parameters.max_text_length)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->button_ok->setEnabled(is_valid); | 
					
						
							|  |  |  |             ui->button_ok_shift->setEnabled(is_valid); | 
					
						
							|  |  |  |             ui->button_ok_num->setEnabled(is_valid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->text_edit_osk->setFocus(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         connect(ui->text_edit_osk, &QTextEdit::cursorPositionChanged, [this] { | 
					
						
							|  |  |  |             const auto new_cursor_position = ui->text_edit_osk->textCursor().position(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                              new_cursor_position > 0); | 
					
						
							|  |  |  |             ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                                    new_cursor_position > 0); | 
					
						
							|  |  |  |             ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                                  new_cursor_position > 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->text_edit_osk->setFocus(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->text_edit_osk->setPlaceholderText( | 
					
						
							|  |  |  |             QString::fromStdU16String(initialize_parameters.guide_text)); | 
					
						
							|  |  |  |         ui->text_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text)); | 
					
						
							|  |  |  |         ui->text_edit_osk->moveCursor(initialize_parameters.initial_cursor_position == 0 | 
					
						
							|  |  |  |                                           ? QTextCursor::Start | 
					
						
							|  |  |  |                                           : QTextCursor::End); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->label_characters_box->setText(QStringLiteral("%1/%2") | 
					
						
							|  |  |  |                                               .arg(initialize_parameters.initial_text.size()) | 
					
						
							|  |  |  |                                               .arg(initialize_parameters.max_text_length)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::SetControllerImage() { | 
					
						
							|  |  |  |     const auto controller_type = Settings::values.players.GetValue()[8].connected | 
					
						
							|  |  |  |                                      ? Settings::values.players.GetValue()[8].controller_type | 
					
						
							|  |  |  |                                      : Settings::values.players.GetValue()[0].controller_type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QString theme = [] { | 
					
						
							|  |  |  |         if (QIcon::themeName().contains(QStringLiteral("dark")) || | 
					
						
							|  |  |  |             QIcon::themeName().contains(QStringLiteral("midnight"))) { | 
					
						
							|  |  |  |             return QStringLiteral("_dark"); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return QString{}; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (controller_type) { | 
					
						
							|  |  |  |     case Settings::ControllerType::ProController: | 
					
						
							|  |  |  |     case Settings::ControllerType::GameCube: | 
					
						
							|  |  |  |         ui->icon_controller->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_shift->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_num->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::ControllerType::DualJoyconDetached: | 
					
						
							|  |  |  |         ui->icon_controller->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_shift->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_num->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::ControllerType::LeftJoycon: | 
					
						
							|  |  |  |         ui->icon_controller->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") | 
					
						
							|  |  |  |                 .arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_shift->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") | 
					
						
							|  |  |  |                 .arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_num->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") | 
					
						
							|  |  |  |                 .arg(theme)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::ControllerType::RightJoycon: | 
					
						
							|  |  |  |         ui->icon_controller->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") | 
					
						
							|  |  |  |                 .arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_shift->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") | 
					
						
							|  |  |  |                 .arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_num->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") | 
					
						
							|  |  |  |                 .arg(theme)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::ControllerType::Handheld: | 
					
						
							|  |  |  |         ui->icon_controller->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_shift->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); | 
					
						
							|  |  |  |         ui->icon_controller_num->setStyleSheet( | 
					
						
							|  |  |  |             QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-11-09 20:13:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | void QtSoftwareKeyboardDialog::DisableKeyboardButtons() { | 
					
						
							|  |  |  |     switch (bottom_osk_index) { | 
					
						
							|  |  |  |     case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |     case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |     default: { | 
					
						
							|  |  |  |         for (const auto& keys : keyboard_buttons) { | 
					
						
							|  |  |  |             for (const auto& rows : keys) { | 
					
						
							|  |  |  |                 for (auto* button : rows) { | 
					
						
							|  |  |  |                     if (!button) { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2018-11-09 20:13:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  |                     button->setEnabled(true); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-11-09 20:13:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  |         const auto& key_disable_flags = initialize_parameters.key_disable_flags; | 
					
						
							| 
									
										
										
										
											2018-11-09 20:13:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  |         ui->button_space->setDisabled(key_disable_flags.space); | 
					
						
							|  |  |  |         ui->button_space_shift->setDisabled(key_disable_flags.space); | 
					
						
							| 
									
										
										
										
											2018-11-11 16:39:25 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  |         ui->button_at->setDisabled(key_disable_flags.at || key_disable_flags.username); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->button_percent->setDisabled(key_disable_flags.percent || key_disable_flags.username); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->button_slash->setDisabled(key_disable_flags.slash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->button_1->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_2->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_3->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_4->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_5->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_6->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_7->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_8->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_9->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  |         ui->button_0->setDisabled(key_disable_flags.numbers); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->button_return->setEnabled(initialize_parameters.enable_return_button); | 
					
						
							|  |  |  |         ui->button_return_shift->setEnabled(initialize_parameters.enable_return_button); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case BottomOSKIndex::NumberPad: { | 
					
						
							|  |  |  |         for (const auto& rows : numberpad_buttons) { | 
					
						
							|  |  |  |             for (auto* button : rows) { | 
					
						
							|  |  |  |                 if (!button) { | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 button->setEnabled(true); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::SetBackspaceOkEnabled() { | 
					
						
							|  |  |  |     if (is_inline) { | 
					
						
							|  |  |  |         ui->button_ok->setEnabled(current_text.size() >= initialize_parameters.min_text_length); | 
					
						
							|  |  |  |         ui->button_ok_shift->setEnabled(current_text.size() >= | 
					
						
							|  |  |  |                                         initialize_parameters.min_text_length); | 
					
						
							|  |  |  |         ui->button_ok_num->setEnabled(current_text.size() >= initialize_parameters.min_text_length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                          cursor_position > 0); | 
					
						
							|  |  |  |         ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                                cursor_position > 0); | 
					
						
							|  |  |  |         ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                              cursor_position > 0); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         const auto text_length = [this] { | 
					
						
							|  |  |  |             if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |                 return static_cast<u32>(ui->text_edit_osk->toPlainText().length()); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 return static_cast<u32>(ui->line_edit_osk->text().length()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const auto normal_cursor_position = [this] { | 
					
						
							|  |  |  |             if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |                 return ui->text_edit_osk->textCursor().position(); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 return ui->line_edit_osk->cursorPosition(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->button_ok->setEnabled(text_length >= initialize_parameters.min_text_length); | 
					
						
							|  |  |  |         ui->button_ok_shift->setEnabled(text_length >= initialize_parameters.min_text_length); | 
					
						
							|  |  |  |         ui->button_ok_num->setEnabled(text_length >= initialize_parameters.min_text_length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                          normal_cursor_position > 0); | 
					
						
							|  |  |  |         ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                                normal_cursor_position > 0); | 
					
						
							|  |  |  |         ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && | 
					
						
							|  |  |  |                                              normal_cursor_position > 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool QtSoftwareKeyboardDialog::ValidateInputText(const QString& input_text) { | 
					
						
							|  |  |  |     const auto& key_disable_flags = initialize_parameters.key_disable_flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto input_text_length = static_cast<u32>(input_text.length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (input_text_length < initialize_parameters.min_text_length || | 
					
						
							|  |  |  |         input_text_length > initialize_parameters.max_text_length) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (key_disable_flags.space && input_text.contains(QLatin1Char{' '})) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((key_disable_flags.at || key_disable_flags.username) && | 
					
						
							|  |  |  |         input_text.contains(QLatin1Char{'@'})) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((key_disable_flags.percent || key_disable_flags.username) && | 
					
						
							|  |  |  |         input_text.contains(QLatin1Char{'%'})) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (key_disable_flags.slash && input_text.contains(QLatin1Char{'/'})) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((key_disable_flags.backslash || key_disable_flags.username) && | 
					
						
							|  |  |  |         input_text.contains(QLatin1Char('\\'))) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (key_disable_flags.numbers && | 
					
						
							|  |  |  |         std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return c.isDigit(); })) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (bottom_osk_index == BottomOSKIndex::NumberPad && | 
					
						
							|  |  |  |         std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return !c.isDigit(); })) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() { | 
					
						
							|  |  |  |     switch (bottom_osk_index) { | 
					
						
							|  |  |  |     case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |         bottom_osk_index = BottomOSKIndex::UpperCase; | 
					
						
							|  |  |  |         ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ui->button_shift_shift->setStyleSheet( | 
					
						
							| 
									
										
										
										
											2021-04-24 13:47:04 -04:00
										 |  |  |             QStringLiteral("image: url(:/overlay/osk_button_shift_lock_off.png);" | 
					
						
							|  |  |  |                            "\nimage-position: left;")); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | 
					
						
							|  |  |  |         ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |         if (caps_lock_enabled) { | 
					
						
							|  |  |  |             caps_lock_enabled = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->button_shift_shift->setStyleSheet( | 
					
						
							| 
									
										
										
										
											2021-04-24 13:47:04 -04:00
										 |  |  |                 QStringLiteral("image: url(:/overlay/osk_button_shift_lock_off.png);" | 
					
						
							|  |  |  |                                "\nimage-position: left;")); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | 
					
						
							|  |  |  |             ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->label_shift_shift->setText(QStringLiteral("Caps Lock")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             bottom_osk_index = BottomOSKIndex::LowerCase; | 
					
						
							|  |  |  |             ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             caps_lock_enabled = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->button_shift_shift->setStyleSheet( | 
					
						
							| 
									
										
										
										
											2021-04-24 13:47:04 -04:00
										 |  |  |                 QStringLiteral("image: url(:/overlay/osk_button_shift_lock_on.png);" | 
					
						
							|  |  |  |                                "\nimage-position: left;")); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | 
					
						
							|  |  |  |             ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ui->label_shift_shift->setText(QStringLiteral("Caps Lock Off")); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case BottomOSKIndex::NumberPad: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button) { | 
					
						
							|  |  |  |     if (button == ui->button_ampersand) { | 
					
						
							|  |  |  |         if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |             ui->text_edit_osk->insertPlainText(QStringLiteral("&")); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ui->line_edit_osk->insert(QStringLiteral("&")); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_return || button == ui->button_return_shift) { | 
					
						
							|  |  |  |         if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |             ui->text_edit_osk->insertPlainText(QStringLiteral("\n")); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ui->line_edit_osk->insert(QStringLiteral("\n")); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_space || button == ui->button_space_shift) { | 
					
						
							|  |  |  |         if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |             ui->text_edit_osk->insertPlainText(QStringLiteral(" ")); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ui->line_edit_osk->insert(QStringLiteral(" ")); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_shift || button == ui->button_shift_shift) { | 
					
						
							|  |  |  |         ChangeBottomOSKIndex(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_backspace || button == ui->button_backspace_shift || | 
					
						
							|  |  |  |         button == ui->button_backspace_num) { | 
					
						
							|  |  |  |         if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |             auto text_cursor = ui->text_edit_osk->textCursor(); | 
					
						
							|  |  |  |             ui->text_edit_osk->setTextCursor(text_cursor); | 
					
						
							|  |  |  |             text_cursor.deletePreviousChar(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ui->line_edit_osk->backspace(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { | 
					
						
							| 
									
										
										
										
											2021-05-27 23:22:38 -04:00
										 |  |  |         auto text = ui->topOSK->currentIndex() == 1 | 
					
						
							|  |  |  |                         ? ui->text_edit_osk->toPlainText().toStdU16String() | 
					
						
							|  |  |  |                         : ui->line_edit_osk->text().toStdU16String(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         emit SubmitNormalText(SwkbdResult::Ok, std::move(text)); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |         ui->text_edit_osk->insertPlainText(button->text()); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ui->line_edit_osk->insert(button->text()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Revert the keyboard to lowercase if the shift key is active.
 | 
					
						
							|  |  |  |     if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { | 
					
						
							|  |  |  |         // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase
 | 
					
						
							|  |  |  |         // if bottom_osk_index is UpperCase and caps_lock_enabled is true.
 | 
					
						
							|  |  |  |         caps_lock_enabled = true; | 
					
						
							|  |  |  |         ChangeBottomOSKIndex(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::InlineKeyboardButtonClicked(QPushButton* button) { | 
					
						
							|  |  |  |     if (!button->isEnabled()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_ampersand) { | 
					
						
							|  |  |  |         InlineTextInsertString(u"&"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_return || button == ui->button_return_shift) { | 
					
						
							|  |  |  |         InlineTextInsertString(u"\n"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_space || button == ui->button_space_shift) { | 
					
						
							|  |  |  |         InlineTextInsertString(u" "); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_shift || button == ui->button_shift_shift) { | 
					
						
							|  |  |  |         ChangeBottomOSKIndex(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_backspace || button == ui->button_backspace_shift || | 
					
						
							|  |  |  |         button == ui->button_backspace_num) { | 
					
						
							|  |  |  |         if (cursor_position <= 0 || current_text.empty()) { | 
					
						
							|  |  |  |             cursor_position = 0; | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         --cursor_position; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         current_text.erase(cursor_position, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         SetBackspaceOkEnabled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { | 
					
						
							|  |  |  |         emit SubmitInlineText(SwkbdReplyType::DecidedEnter, current_text, cursor_position); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InlineTextInsertString(button->text().toStdU16String()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Revert the keyboard to lowercase if the shift key is active.
 | 
					
						
							|  |  |  |     if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { | 
					
						
							|  |  |  |         // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase
 | 
					
						
							|  |  |  |         // if bottom_osk_index is UpperCase and caps_lock_enabled is true.
 | 
					
						
							|  |  |  |         caps_lock_enabled = true; | 
					
						
							|  |  |  |         ChangeBottomOSKIndex(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::InlineTextInsertString(std::u16string_view string) { | 
					
						
							|  |  |  |     if ((current_text.size() + string.size()) > initialize_parameters.max_text_length) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     current_text.insert(cursor_position, string); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursor_position += static_cast<s32>(string.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SetBackspaceOkEnabled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::SetupMouseHover() { | 
					
						
							|  |  |  |     // setFocus() has a bug where continuously changing focus will cause the focus UI to
 | 
					
						
							|  |  |  |     // mysteriously disappear. A workaround we have found is using the mouse to hover over
 | 
					
						
							|  |  |  |     // the buttons to act in place of the button focus. As a result, we will have to set
 | 
					
						
							|  |  |  |     // a blank cursor when hovering over all the buttons and set a no focus policy so the
 | 
					
						
							|  |  |  |     // buttons do not stay in focus in addition to the mouse hover.
 | 
					
						
							|  |  |  |     for (auto* button : all_buttons) { | 
					
						
							|  |  |  |         button->setCursor(QCursor(Qt::BlankCursor)); | 
					
						
							|  |  |  |         button->setFocusPolicy(Qt::NoFocus); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <HIDButton... T> | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() { | 
					
						
							|  |  |  |     const auto f = [this](HIDButton button) { | 
					
						
							|  |  |  |         if (input_interpreter->IsButtonPressedOnce(button)) { | 
					
						
							|  |  |  |             TranslateButtonPress(button); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     (f(T), ...); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <HIDButton... T> | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::HandleButtonHold() { | 
					
						
							|  |  |  |     const auto f = [this](HIDButton button) { | 
					
						
							|  |  |  |         if (input_interpreter->IsButtonHeld(button)) { | 
					
						
							|  |  |  |             TranslateButtonPress(button); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     (f(T), ...); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) { | 
					
						
							|  |  |  |     switch (button) { | 
					
						
							|  |  |  |     case HIDButton::A: | 
					
						
							|  |  |  |         switch (bottom_osk_index) { | 
					
						
							|  |  |  |         case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |         case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |             keyboard_buttons[static_cast<std::size_t>(bottom_osk_index)][row][column]->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::NumberPad: | 
					
						
							|  |  |  |             numberpad_buttons[row][column]->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::B: | 
					
						
							|  |  |  |         switch (bottom_osk_index) { | 
					
						
							|  |  |  |         case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |             ui->button_backspace->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |             ui->button_backspace_shift->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::NumberPad: | 
					
						
							|  |  |  |             ui->button_backspace_num->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::X: | 
					
						
							|  |  |  |         if (is_inline) { | 
					
						
							|  |  |  |             emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-05-27 23:22:38 -04:00
										 |  |  |             auto text = ui->topOSK->currentIndex() == 1 | 
					
						
							|  |  |  |                             ? ui->text_edit_osk->toPlainText().toStdU16String() | 
					
						
							|  |  |  |                             : ui->line_edit_osk->text().toStdU16String(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             emit SubmitNormalText(SwkbdResult::Cancel, std::move(text)); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::Y: | 
					
						
							|  |  |  |         switch (bottom_osk_index) { | 
					
						
							|  |  |  |         case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |             ui->button_space->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |             ui->button_space_shift->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::NumberPad: | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::LStick: | 
					
						
							|  |  |  |     case HIDButton::RStick: | 
					
						
							|  |  |  |         switch (bottom_osk_index) { | 
					
						
							|  |  |  |         case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |             ui->button_shift->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |             ui->button_shift_shift->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::NumberPad: | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::L: | 
					
						
							|  |  |  |         MoveTextCursorDirection(Direction::Left); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::R: | 
					
						
							|  |  |  |         MoveTextCursorDirection(Direction::Right); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::Plus: | 
					
						
							|  |  |  |         switch (bottom_osk_index) { | 
					
						
							|  |  |  |         case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |             ui->button_ok->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::UpperCase: | 
					
						
							|  |  |  |             ui->button_ok_shift->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case BottomOSKIndex::NumberPad: | 
					
						
							|  |  |  |             ui->button_ok_num->click(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::DLeft: | 
					
						
							|  |  |  |     case HIDButton::LStickLeft: | 
					
						
							|  |  |  |     case HIDButton::RStickLeft: | 
					
						
							|  |  |  |         MoveButtonDirection(Direction::Left); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::DUp: | 
					
						
							|  |  |  |     case HIDButton::LStickUp: | 
					
						
							|  |  |  |     case HIDButton::RStickUp: | 
					
						
							|  |  |  |         MoveButtonDirection(Direction::Up); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::DRight: | 
					
						
							|  |  |  |     case HIDButton::LStickRight: | 
					
						
							|  |  |  |     case HIDButton::RStickRight: | 
					
						
							|  |  |  |         MoveButtonDirection(Direction::Right); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case HIDButton::DDown: | 
					
						
							|  |  |  |     case HIDButton::LStickDown: | 
					
						
							|  |  |  |     case HIDButton::RStickDown: | 
					
						
							|  |  |  |         MoveButtonDirection(Direction::Down); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::MoveButtonDirection(Direction direction) { | 
					
						
							|  |  |  |     // Changes the row or column index depending on the direction.
 | 
					
						
							|  |  |  |     auto move_direction = [this, direction](std::size_t max_rows, std::size_t max_columns) { | 
					
						
							|  |  |  |         switch (direction) { | 
					
						
							|  |  |  |         case Direction::Left: | 
					
						
							|  |  |  |             column = (column + max_columns - 1) % max_columns; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case Direction::Up: | 
					
						
							|  |  |  |             row = (row + max_rows - 1) % max_rows; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case Direction::Right: | 
					
						
							|  |  |  |             column = (column + 1) % max_columns; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case Direction::Down: | 
					
						
							|  |  |  |             row = (row + 1) % max_rows; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (bottom_osk_index) { | 
					
						
							|  |  |  |     case BottomOSKIndex::LowerCase: | 
					
						
							|  |  |  |     case BottomOSKIndex::UpperCase: { | 
					
						
							|  |  |  |         const auto index = static_cast<std::size_t>(bottom_osk_index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const auto* const prev_button = keyboard_buttons[index][row][column]; | 
					
						
							|  |  |  |         move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL); | 
					
						
							|  |  |  |         auto* curr_button = keyboard_buttons[index][row][column]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) { | 
					
						
							|  |  |  |             move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL); | 
					
						
							|  |  |  |             curr_button = keyboard_buttons[index][row][column]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // This is a workaround for setFocus() randomly not showing focus in the UI
 | 
					
						
							|  |  |  |         QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case BottomOSKIndex::NumberPad: { | 
					
						
							|  |  |  |         const auto* const prev_button = numberpad_buttons[row][column]; | 
					
						
							|  |  |  |         move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD); | 
					
						
							|  |  |  |         auto* curr_button = numberpad_buttons[row][column]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) { | 
					
						
							|  |  |  |             move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD); | 
					
						
							|  |  |  |             curr_button = numberpad_buttons[row][column]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // This is a workaround for setFocus() randomly not showing focus in the UI
 | 
					
						
							|  |  |  |         QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::MoveTextCursorDirection(Direction direction) { | 
					
						
							|  |  |  |     switch (direction) { | 
					
						
							|  |  |  |     case Direction::Left: | 
					
						
							|  |  |  |         if (is_inline) { | 
					
						
							|  |  |  |             if (cursor_position <= 0) { | 
					
						
							|  |  |  |                 cursor_position = 0; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 --cursor_position; | 
					
						
							|  |  |  |                 emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |                 ui->text_edit_osk->moveCursor(QTextCursor::Left); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() - 1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Direction::Right: | 
					
						
							|  |  |  |         if (is_inline) { | 
					
						
							|  |  |  |             if (cursor_position >= static_cast<s32>(current_text.size())) { | 
					
						
							|  |  |  |                 cursor_position = static_cast<s32>(current_text.size()); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 ++cursor_position; | 
					
						
							|  |  |  |                 emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (ui->topOSK->currentIndex() == 1) { | 
					
						
							|  |  |  |                 ui->text_edit_osk->moveCursor(QTextCursor::Right); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() + 1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::StartInputThread() { | 
					
						
							|  |  |  |     if (input_thread_running) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     input_thread_running = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     input_thread = std::thread(&QtSoftwareKeyboardDialog::InputThread, this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::StopInputThread() { | 
					
						
							|  |  |  |     input_thread_running = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (input_thread.joinable()) { | 
					
						
							|  |  |  |         input_thread.join(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (input_interpreter) { | 
					
						
							|  |  |  |         input_interpreter->ResetButtonStates(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboardDialog::InputThread() { | 
					
						
							|  |  |  |     while (input_thread_running) { | 
					
						
							|  |  |  |         input_interpreter->PollInput(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::X, HIDButton::Y, | 
					
						
							|  |  |  |                                 HIDButton::LStick, HIDButton::RStick, HIDButton::L, HIDButton::R, | 
					
						
							|  |  |  |                                 HIDButton::Plus, HIDButton::DLeft, HIDButton::DUp, | 
					
						
							|  |  |  |                                 HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft, | 
					
						
							|  |  |  |                                 HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown, | 
					
						
							|  |  |  |                                 HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight, | 
					
						
							|  |  |  |                                 HIDButton::RStickDown>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         HandleButtonHold<HIDButton::B, HIDButton::L, HIDButton::R, HIDButton::DLeft, HIDButton::DUp, | 
					
						
							|  |  |  |                          HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft, | 
					
						
							|  |  |  |                          HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown, | 
					
						
							|  |  |  |                          HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight, | 
					
						
							|  |  |  |                          HIDButton::RStickDown>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         std::this_thread::sleep_for(std::chrono::milliseconds(50)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { | 
					
						
							|  |  |  |     connect(this, &QtSoftwareKeyboard::MainWindowInitializeKeyboard, &main_window, | 
					
						
							|  |  |  |             &GMainWindow::SoftwareKeyboardInitialize, Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(this, &QtSoftwareKeyboard::MainWindowShowNormalKeyboard, &main_window, | 
					
						
							|  |  |  |             &GMainWindow::SoftwareKeyboardShowNormal, Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(this, &QtSoftwareKeyboard::MainWindowShowTextCheckDialog, &main_window, | 
					
						
							|  |  |  |             &GMainWindow::SoftwareKeyboardShowTextCheck, Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(this, &QtSoftwareKeyboard::MainWindowShowInlineKeyboard, &main_window, | 
					
						
							|  |  |  |             &GMainWindow::SoftwareKeyboardShowInline, Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(this, &QtSoftwareKeyboard::MainWindowHideInlineKeyboard, &main_window, | 
					
						
							|  |  |  |             &GMainWindow::SoftwareKeyboardHideInline, Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(this, &QtSoftwareKeyboard::MainWindowInlineTextChanged, &main_window, | 
					
						
							|  |  |  |             &GMainWindow::SoftwareKeyboardInlineTextChanged, Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(this, &QtSoftwareKeyboard::MainWindowExitKeyboard, &main_window, | 
					
						
							|  |  |  |             &GMainWindow::SoftwareKeyboardExit, Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitNormalText, this, | 
					
						
							|  |  |  |             &QtSoftwareKeyboard::SubmitNormalText, Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitInlineText, this, | 
					
						
							|  |  |  |             &QtSoftwareKeyboard::SubmitInlineText, Qt::QueuedConnection); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-11-11 16:39:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::InitializeKeyboard( | 
					
						
							|  |  |  |     bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, | 
					
						
							|  |  |  |     std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_, | 
					
						
							|  |  |  |     std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | 
					
						
							|  |  |  |         submit_inline_callback_) { | 
					
						
							|  |  |  |     if (is_inline) { | 
					
						
							|  |  |  |         submit_inline_callback = std::move(submit_inline_callback_); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         submit_normal_callback = std::move(submit_normal_callback_); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     LOG_INFO(Service_AM, | 
					
						
							|  |  |  |              "\nKeyboardInitializeParameters:" | 
					
						
							|  |  |  |              "\nok_text={}" | 
					
						
							|  |  |  |              "\nheader_text={}" | 
					
						
							|  |  |  |              "\nsub_text={}" | 
					
						
							|  |  |  |              "\nguide_text={}" | 
					
						
							|  |  |  |              "\ninitial_text={}" | 
					
						
							|  |  |  |              "\nmax_text_length={}" | 
					
						
							|  |  |  |              "\nmin_text_length={}" | 
					
						
							|  |  |  |              "\ninitial_cursor_position={}" | 
					
						
							|  |  |  |              "\ntype={}" | 
					
						
							|  |  |  |              "\npassword_mode={}" | 
					
						
							|  |  |  |              "\ntext_draw_type={}" | 
					
						
							|  |  |  |              "\nkey_disable_flags={}" | 
					
						
							|  |  |  |              "\nuse_blur_background={}" | 
					
						
							|  |  |  |              "\nenable_backspace_button={}" | 
					
						
							|  |  |  |              "\nenable_return_button={}" | 
					
						
							|  |  |  |              "\ndisable_cancel_button={}", | 
					
						
							|  |  |  |              Common::UTF16ToUTF8(initialize_parameters.ok_text), | 
					
						
							|  |  |  |              Common::UTF16ToUTF8(initialize_parameters.header_text), | 
					
						
							|  |  |  |              Common::UTF16ToUTF8(initialize_parameters.sub_text), | 
					
						
							|  |  |  |              Common::UTF16ToUTF8(initialize_parameters.guide_text), | 
					
						
							|  |  |  |              Common::UTF16ToUTF8(initialize_parameters.initial_text), | 
					
						
							|  |  |  |              initialize_parameters.max_text_length, initialize_parameters.min_text_length, | 
					
						
							|  |  |  |              initialize_parameters.initial_cursor_position, initialize_parameters.type, | 
					
						
							|  |  |  |              initialize_parameters.password_mode, initialize_parameters.text_draw_type, | 
					
						
							|  |  |  |              initialize_parameters.key_disable_flags.raw, initialize_parameters.use_blur_background, | 
					
						
							|  |  |  |              initialize_parameters.enable_backspace_button, | 
					
						
							|  |  |  |              initialize_parameters.enable_return_button, | 
					
						
							|  |  |  |              initialize_parameters.disable_cancel_button); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     emit MainWindowInitializeKeyboard(is_inline, std::move(initialize_parameters)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::ShowNormalKeyboard() const { | 
					
						
							|  |  |  |     emit MainWindowShowNormalKeyboard(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::ShowTextCheckDialog( | 
					
						
							|  |  |  |     Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 
					
						
							|  |  |  |     std::u16string text_check_message) const { | 
					
						
							| 
									
										
										
										
											2021-05-27 23:22:38 -04:00
										 |  |  |     emit MainWindowShowTextCheckDialog(text_check_result, std::move(text_check_message)); | 
					
						
							| 
									
										
										
										
											2021-03-27 15:15:32 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::ShowInlineKeyboard( | 
					
						
							|  |  |  |     Core::Frontend::InlineAppearParameters appear_parameters) const { | 
					
						
							|  |  |  |     LOG_INFO(Service_AM, | 
					
						
							|  |  |  |              "\nInlineAppearParameters:" | 
					
						
							|  |  |  |              "\nmax_text_length={}" | 
					
						
							|  |  |  |              "\nmin_text_length={}" | 
					
						
							|  |  |  |              "\nkey_top_scale_x={}" | 
					
						
							|  |  |  |              "\nkey_top_scale_y={}" | 
					
						
							|  |  |  |              "\nkey_top_translate_x={}" | 
					
						
							|  |  |  |              "\nkey_top_translate_y={}" | 
					
						
							|  |  |  |              "\ntype={}" | 
					
						
							|  |  |  |              "\nkey_disable_flags={}" | 
					
						
							|  |  |  |              "\nkey_top_as_floating={}" | 
					
						
							|  |  |  |              "\nenable_backspace_button={}" | 
					
						
							|  |  |  |              "\nenable_return_button={}" | 
					
						
							|  |  |  |              "\ndisable_cancel_button={}", | 
					
						
							|  |  |  |              appear_parameters.max_text_length, appear_parameters.min_text_length, | 
					
						
							|  |  |  |              appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y, | 
					
						
							|  |  |  |              appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y, | 
					
						
							|  |  |  |              appear_parameters.type, appear_parameters.key_disable_flags.raw, | 
					
						
							|  |  |  |              appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button, | 
					
						
							|  |  |  |              appear_parameters.enable_return_button, appear_parameters.disable_cancel_button); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     emit MainWindowShowInlineKeyboard(std::move(appear_parameters)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::HideInlineKeyboard() const { | 
					
						
							|  |  |  |     emit MainWindowHideInlineKeyboard(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::InlineTextChanged( | 
					
						
							|  |  |  |     Core::Frontend::InlineTextParameters text_parameters) const { | 
					
						
							|  |  |  |     LOG_INFO(Service_AM, | 
					
						
							|  |  |  |              "\nInlineTextParameters:" | 
					
						
							|  |  |  |              "\ninput_text={}" | 
					
						
							|  |  |  |              "\ncursor_position={}", | 
					
						
							|  |  |  |              Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     emit MainWindowInlineTextChanged(std::move(text_parameters)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::ExitKeyboard() const { | 
					
						
							|  |  |  |     emit MainWindowExitKeyboard(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result, | 
					
						
							|  |  |  |                                           std::u16string submitted_text) const { | 
					
						
							|  |  |  |     submit_normal_callback(result, submitted_text); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | 
					
						
							|  |  |  |                                           std::u16string submitted_text, | 
					
						
							|  |  |  |                                           s32 cursor_position) const { | 
					
						
							|  |  |  |     submit_inline_callback(reply_type, submitted_text, cursor_position); | 
					
						
							|  |  |  | } |