aboutsummaryrefslogtreecommitdiff
path: root/src/yuzu/util/overlay_dialog.h
blob: 62f9da311d058522355ffb6f5970cfb04df38ab3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <atomic>
#include <memory>
#include <thread>

#include <QDialog>

#include "common/common_types.h"

class InputInterpreter;

namespace Core {
class System;
}

namespace Core::HID {
enum class NpadButton : u64;
}

namespace Ui {
class OverlayDialog;
}

/**
 * An OverlayDialog is an interactive dialog that accepts controller input (while a game is running)
 * This dialog attempts to replicate the look and feel of the Nintendo Switch's overlay dialogs and
 * provide some extra features such as embedding HTML/Rich Text content in a QTextBrowser.
 * The OverlayDialog provides 2 modes: one to embed regular text into a QLabel and another to embed
 * HTML/Rich Text content into a QTextBrowser.
 */
class OverlayDialog final : public QDialog {
    Q_OBJECT

public:
    explicit OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text,
                           const QString& body_text, const QString& left_button_text,
                           const QString& right_button_text,
                           Qt::Alignment alignment = Qt::AlignCenter, bool use_rich_text_ = false);
    ~OverlayDialog() override;

private:
    /**
     * Initializes a text dialog with a QLabel storing text.
     * Only use this for short text as the dialog buttons would be squashed with longer text.
     *
     * @param title_text Title text to be displayed
     * @param body_text Main text to be displayed
     * @param left_button_text Left button text. If empty, the button is hidden and disabled
     * @param right_button_text Right button text. If empty, the button is hidden and disabled
     * @param alignment Main text alignment
     */
    void InitializeRegularTextDialog(const QString& title_text, const QString& body_text,
                                     const QString& left_button_text,
                                     const QString& right_button_text, Qt::Alignment alignment);

    /**
     * Initializes a text dialog with a QTextBrowser storing text.
     * This is ideal for longer text or rich text content. A scrollbar is shown for longer text.
     *
     * @param title_text Title text to be displayed
     * @param body_text Main text to be displayed
     * @param left_button_text Left button text. If empty, the button is hidden and disabled
     * @param right_button_text Right button text. If empty, the button is hidden and disabled
     * @param alignment Main text alignment
     */
    void InitializeRichTextDialog(const QString& title_text, const QString& body_text,
                                  const QString& left_button_text, const QString& right_button_text,
                                  Qt::Alignment alignment);

    /// Moves and resizes the dialog to be fully overlaid on top of the parent window.
    void MoveAndResizeWindow();

    /**
     * Handles button presses and converts them into keyboard input.
     *
     * @tparam HIDButton The list of buttons that can be converted into keyboard input.
     */
    template <Core::HID::NpadButton... T>
    void HandleButtonPressedOnce();

    /**
     * Translates a button press to focus or click either the left or right buttons.
     *
     * @param button The button press to process.
     */
    void TranslateButtonPress(Core::HID::NpadButton button);

    void StartInputThread();
    void StopInputThread();

    /// The thread where input is being polled and processed.
    void InputThread();
    void keyPressEvent(QKeyEvent* e) override;

    std::unique_ptr<Ui::OverlayDialog> ui;

    bool use_rich_text;

    std::unique_ptr<InputInterpreter> input_interpreter;

    std::thread input_thread;

    std::atomic<bool> input_thread_running{};
};