| | |
| | |
| |
|
| | #include <QKeyEvent> |
| | #include <QScreen> |
| | #include <QWindow> |
| |
|
| | #include "core/core.h" |
| | #include "hid_core/frontend/input_interpreter.h" |
| | #include "hid_core/hid_types.h" |
| | #include "ui_overlay_dialog.h" |
| | #include "yuzu/util/overlay_dialog.h" |
| |
|
| | namespace { |
| |
|
| | constexpr float BASE_TITLE_FONT_SIZE = 14.0f; |
| | constexpr float BASE_FONT_SIZE = 18.0f; |
| | constexpr float BASE_WIDTH = 1280.0f; |
| | constexpr float BASE_HEIGHT = 720.0f; |
| |
|
| | } |
| |
|
| | OverlayDialog::OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text, |
| | const QString& body_text, const QString& left_button_text, |
| | const QString& right_button_text, Qt::Alignment alignment, |
| | bool use_rich_text_) |
| | : QDialog(parent), ui{std::make_unique<Ui::OverlayDialog>()}, use_rich_text{use_rich_text_} { |
| | ui->setupUi(this); |
| |
|
| | setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint | |
| | Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint); |
| | setWindowModality(Qt::WindowModal); |
| | setAttribute(Qt::WA_TranslucentBackground); |
| |
|
| | if (use_rich_text) { |
| | InitializeRichTextDialog(title_text, body_text, left_button_text, right_button_text, |
| | alignment); |
| | } else { |
| | InitializeRegularTextDialog(title_text, body_text, left_button_text, right_button_text, |
| | alignment); |
| | } |
| |
|
| | MoveAndResizeWindow(); |
| |
|
| | |
| | if (system.IsPoweredOn() && !ui->buttonsDialog->isHidden()) { |
| | input_interpreter = std::make_unique<InputInterpreter>(system); |
| |
|
| | StartInputThread(); |
| | } |
| | } |
| |
|
| | OverlayDialog::~OverlayDialog() { |
| | StopInputThread(); |
| | } |
| |
|
| | void OverlayDialog::InitializeRegularTextDialog(const QString& title_text, const QString& body_text, |
| | const QString& left_button_text, |
| | const QString& right_button_text, |
| | Qt::Alignment alignment) { |
| | ui->stackedDialog->setCurrentIndex(0); |
| |
|
| | ui->label_title->setText(title_text); |
| | ui->label_dialog->setText(body_text); |
| | ui->button_cancel->setText(left_button_text); |
| | ui->button_ok_label->setText(right_button_text); |
| |
|
| | ui->label_dialog->setAlignment(alignment); |
| |
|
| | if (title_text.isEmpty()) { |
| | ui->label_title->hide(); |
| | ui->verticalLayout_2->setStretch(0, 0); |
| | ui->verticalLayout_2->setStretch(1, 219); |
| | ui->verticalLayout_2->setStretch(2, 82); |
| | } |
| |
|
| | if (left_button_text.isEmpty()) { |
| | ui->button_cancel->hide(); |
| | ui->button_cancel->setEnabled(false); |
| | } |
| |
|
| | if (right_button_text.isEmpty()) { |
| | ui->button_ok_label->hide(); |
| | ui->button_ok_label->setEnabled(false); |
| | } |
| |
|
| | if (ui->button_cancel->isHidden() && ui->button_ok_label->isHidden()) { |
| | ui->buttonsDialog->hide(); |
| | return; |
| | } |
| |
|
| | connect( |
| | ui->button_cancel, &QPushButton::clicked, this, |
| | [this](bool) { |
| | StopInputThread(); |
| | QDialog::reject(); |
| | }, |
| | Qt::QueuedConnection); |
| | connect( |
| | ui->button_ok_label, &QPushButton::clicked, this, |
| | [this](bool) { |
| | StopInputThread(); |
| | QDialog::accept(); |
| | }, |
| | Qt::QueuedConnection); |
| | } |
| |
|
| | void OverlayDialog::InitializeRichTextDialog(const QString& title_text, const QString& body_text, |
| | const QString& left_button_text, |
| | const QString& right_button_text, |
| | Qt::Alignment alignment) { |
| | ui->stackedDialog->setCurrentIndex(1); |
| |
|
| | ui->label_title_rich->setText(title_text); |
| | ui->text_browser_dialog->setText(body_text); |
| | ui->button_cancel_rich->setText(left_button_text); |
| | ui->button_ok_rich->setText(right_button_text); |
| |
|
| | |
| | ui->text_browser_dialog->setAlignment(alignment); |
| |
|
| | if (title_text.isEmpty()) { |
| | ui->label_title_rich->hide(); |
| | ui->verticalLayout_3->setStretch(0, 0); |
| | ui->verticalLayout_3->setStretch(1, 438); |
| | ui->verticalLayout_3->setStretch(2, 82); |
| | } |
| |
|
| | if (left_button_text.isEmpty()) { |
| | ui->button_cancel_rich->hide(); |
| | ui->button_cancel_rich->setEnabled(false); |
| | } |
| |
|
| | if (right_button_text.isEmpty()) { |
| | ui->button_ok_rich->hide(); |
| | ui->button_ok_rich->setEnabled(false); |
| | } |
| |
|
| | if (ui->button_cancel_rich->isHidden() && ui->button_ok_rich->isHidden()) { |
| | ui->buttonsRichDialog->hide(); |
| | return; |
| | } |
| |
|
| | connect( |
| | ui->button_cancel_rich, &QPushButton::clicked, this, |
| | [this](bool) { |
| | StopInputThread(); |
| | QDialog::reject(); |
| | }, |
| | Qt::QueuedConnection); |
| | connect( |
| | ui->button_ok_rich, &QPushButton::clicked, this, |
| | [this](bool) { |
| | StopInputThread(); |
| | QDialog::accept(); |
| | }, |
| | Qt::QueuedConnection); |
| | } |
| |
|
| | void OverlayDialog::MoveAndResizeWindow() { |
| | const auto pos = parentWidget()->mapToGlobal(parentWidget()->rect().topLeft()); |
| | const auto width = static_cast<float>(parentWidget()->width()); |
| | const auto height = static_cast<float>(parentWidget()->height()); |
| |
|
| | |
| | const float dpi_scale = screen()->logicalDotsPerInch() / 96.0f; |
| |
|
| | const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; |
| | const auto body_text_font_size = |
| | BASE_FONT_SIZE * (((width / BASE_WIDTH) + (height / BASE_HEIGHT)) / 2.0f) / dpi_scale; |
| | const auto button_text_font_size = BASE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; |
| |
|
| | QFont title_text_font(QStringLiteral("MS Shell Dlg 2"), title_text_font_size, QFont::Normal); |
| | QFont body_text_font(QStringLiteral("MS Shell Dlg 2"), body_text_font_size, QFont::Normal); |
| | QFont button_text_font(QStringLiteral("MS Shell Dlg 2"), button_text_font_size, QFont::Normal); |
| |
|
| | if (use_rich_text) { |
| | ui->label_title_rich->setFont(title_text_font); |
| | ui->text_browser_dialog->setFont(body_text_font); |
| | ui->button_cancel_rich->setFont(button_text_font); |
| | ui->button_ok_rich->setFont(button_text_font); |
| | } else { |
| | ui->label_title->setFont(title_text_font); |
| | ui->label_dialog->setFont(body_text_font); |
| | ui->button_cancel->setFont(button_text_font); |
| | ui->button_ok_label->setFont(button_text_font); |
| | } |
| |
|
| | QDialog::move(pos); |
| | QDialog::resize(width, height); |
| | } |
| |
|
| | template <Core::HID::NpadButton... T> |
| | void OverlayDialog::HandleButtonPressedOnce() { |
| | const auto f = [this](Core::HID::NpadButton button) { |
| | if (input_interpreter->IsButtonPressedOnce(button)) { |
| | TranslateButtonPress(button); |
| | } |
| | }; |
| |
|
| | (f(T), ...); |
| | } |
| |
|
| | void OverlayDialog::TranslateButtonPress(Core::HID::NpadButton button) { |
| | QPushButton* left_button = use_rich_text ? ui->button_cancel_rich : ui->button_cancel; |
| | QPushButton* right_button = use_rich_text ? ui->button_ok_rich : ui->button_ok_label; |
| |
|
| | |
| | |
| |
|
| | switch (button) { |
| | case Core::HID::NpadButton::A: |
| | case Core::HID::NpadButton::B: |
| | if (left_button->hasFocus()) { |
| | left_button->click(); |
| | } else if (right_button->hasFocus()) { |
| | right_button->click(); |
| | } |
| | break; |
| | case Core::HID::NpadButton::Left: |
| | case Core::HID::NpadButton::StickLLeft: |
| | focusPreviousChild(); |
| | break; |
| | case Core::HID::NpadButton::Right: |
| | case Core::HID::NpadButton::StickLRight: |
| | focusNextChild(); |
| | break; |
| | default: |
| | break; |
| | } |
| | } |
| |
|
| | void OverlayDialog::StartInputThread() { |
| | if (input_thread_running) { |
| | return; |
| | } |
| |
|
| | input_thread_running = true; |
| |
|
| | input_thread = std::thread(&OverlayDialog::InputThread, this); |
| | } |
| |
|
| | void OverlayDialog::StopInputThread() { |
| | input_thread_running = false; |
| |
|
| | if (input_thread.joinable()) { |
| | input_thread.join(); |
| | } |
| | } |
| |
|
| | void OverlayDialog::InputThread() { |
| | while (input_thread_running) { |
| | input_interpreter->PollInput(); |
| |
|
| | HandleButtonPressedOnce<Core::HID::NpadButton::A, Core::HID::NpadButton::B, |
| | Core::HID::NpadButton::Left, Core::HID::NpadButton::Right, |
| | Core::HID::NpadButton::StickLLeft, |
| | Core::HID::NpadButton::StickLRight>(); |
| |
|
| | std::this_thread::sleep_for(std::chrono::milliseconds(50)); |
| | } |
| | } |
| |
|
| | void OverlayDialog::keyPressEvent(QKeyEvent* e) { |
| | if (!ui->buttonsDialog->isHidden() || e->key() != Qt::Key_Escape) { |
| | QDialog::keyPressEvent(e); |
| | } |
| | } |
| |
|