duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

mainwindow.h (11235B)


      1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #pragma once
      5 
      6 #include "controllersettingswindow.h"
      7 #include "displaywidget.h"
      8 #include "settingswindow.h"
      9 #include "ui_mainwindow.h"
     10 
     11 #include "core/types.h"
     12 
     13 #include "util/window_info.h"
     14 
     15 #include <QtCore/QThread>
     16 #include <QtWidgets/QLabel>
     17 #include <QtWidgets/QMainWindow>
     18 #include <QtWidgets/QMenu>
     19 #include <QtWidgets/QStackedWidget>
     20 #include <memory>
     21 #include <optional>
     22 
     23 class QLabel;
     24 class QThread;
     25 class QProgressBar;
     26 
     27 class MainWindow;
     28 class GameListWidget;
     29 class EmuThread;
     30 class AutoUpdaterDialog;
     31 class MemoryCardEditorWindow;
     32 class CheatManagerWindow;
     33 class DebuggerWindow;
     34 class MemoryScannerWindow;
     35 
     36 struct SystemBootParameters;
     37 
     38 class GPUDevice;
     39 namespace Achievements {
     40 enum class LoginRequestReason;
     41 }
     42 namespace GameList {
     43 struct Entry;
     44 }
     45 
     46 class MainWindow final : public QMainWindow
     47 {
     48   Q_OBJECT
     49 
     50 public:
     51   /// This class is a scoped lock on the system, which prevents it from running while
     52   /// the object exists. Its purpose is to be used for blocking/modal popup boxes,
     53   /// where the VM needs to exit fullscreen temporarily.
     54   class SystemLock
     55   {
     56   public:
     57     SystemLock(SystemLock&& lock);
     58     SystemLock(const SystemLock&) = delete;
     59     ~SystemLock();
     60 
     61     /// Returns the parent widget, which can be used for any popup dialogs.
     62     ALWAYS_INLINE QWidget* getDialogParent() const { return m_dialog_parent; }
     63 
     64     /// Cancels any pending unpause/fullscreen transition.
     65     /// Call when you're going to destroy the system anyway.
     66     void cancelResume();
     67 
     68   private:
     69     SystemLock(QWidget* dialog_parent, bool was_paused, bool was_fullscreen);
     70     friend MainWindow;
     71 
     72     QWidget* m_dialog_parent;
     73     bool m_was_paused;
     74     bool m_was_fullscreen;
     75   };
     76 
     77 public:
     78   explicit MainWindow();
     79   ~MainWindow();
     80 
     81   /// Performs update check if enabled in settings.
     82   void startupUpdateCheck();
     83 
     84   /// Opens memory card editor with the specified paths.
     85   void openMemoryCardEditor(const QString& card_a_path, const QString& card_b_path);
     86 
     87   /// Locks the system by pausing it, while a popup dialog is displayed.
     88   SystemLock pauseAndLockSystem();
     89 
     90   /// Force quits the application.
     91   void quit();
     92 
     93   /// Accessors for the status bar widgets, updated by the emulation thread.
     94   ALWAYS_INLINE QLabel* getStatusRendererWidget() const { return m_status_renderer_widget; }
     95   ALWAYS_INLINE QLabel* getStatusResolutionWidget() const { return m_status_resolution_widget; }
     96   ALWAYS_INLINE QLabel* getStatusFPSWidget() const { return m_status_fps_widget; }
     97   ALWAYS_INLINE QLabel* getStatusVPSWidget() const { return m_status_vps_widget; }
     98 
     99   /// Accessors for child windows.
    100   CheatManagerWindow* getCheatManagerWindow() const { return m_cheat_manager_window; }
    101 
    102   /// Opens the editor for a specific input profile.
    103   void openInputProfileEditor(const std::string_view name);
    104 
    105 public Q_SLOTS:
    106   /// Updates debug menu visibility (hides if disabled).
    107   void updateDebugMenuVisibility();
    108 
    109   void refreshGameList(bool invalidate_cache);
    110   void refreshGameListModel();
    111   void cancelGameListRefresh();
    112 
    113   void runOnUIThread(const std::function<void()>& func);
    114   bool requestShutdown(bool allow_confirm = true, bool allow_save_to_state = true, bool save_state = true);
    115   void requestExit(bool allow_confirm = true);
    116   void checkForSettingChanges();
    117   std::optional<WindowInfo> getWindowInfo();
    118 
    119   void checkForUpdates(bool display_message);
    120   void recreate();
    121 
    122   void* getNativeWindowId();
    123 
    124 private Q_SLOTS:
    125   void reportError(const QString& title, const QString& message);
    126   bool confirmMessage(const QString& title, const QString& message);
    127   void onStatusMessage(const QString& message);
    128 
    129   std::optional<WindowInfo> acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main,
    130                                                 bool surfaceless, bool use_main_window_pos);
    131   void displayResizeRequested(qint32 width, qint32 height);
    132   void releaseRenderWindow();
    133   void focusDisplayWidget();
    134   void onMouseModeRequested(bool relative_mode, bool hide_cursor);
    135 
    136   void onSettingsResetToDefault(bool system, bool controller);
    137   void onSystemStarting();
    138   void onSystemStarted();
    139   void onSystemDestroyed();
    140   void onSystemPaused();
    141   void onSystemResumed();
    142   void onRunningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title);
    143   void onMediaCaptureStarted();
    144   void onMediaCaptureStopped();
    145   void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
    146   void onAchievementsChallengeModeChanged(bool enabled);
    147   void onApplicationStateChanged(Qt::ApplicationState state);
    148 
    149   void onStartFileActionTriggered();
    150   void onStartDiscActionTriggered();
    151   void onStartBIOSActionTriggered();
    152   void onChangeDiscFromFileActionTriggered();
    153   void onChangeDiscFromGameListActionTriggered();
    154   void onChangeDiscFromDeviceActionTriggered();
    155   void onChangeDiscMenuAboutToShow();
    156   void onChangeDiscMenuAboutToHide();
    157   void onLoadStateMenuAboutToShow();
    158   void onSaveStateMenuAboutToShow();
    159   void onCheatsActionTriggered();
    160   void onCheatsMenuAboutToShow();
    161   void onStartFullscreenUITriggered();
    162   void onFullscreenUIStateChange(bool running);
    163   void onRemoveDiscActionTriggered();
    164   void onViewToolbarActionToggled(bool checked);
    165   void onViewLockToolbarActionToggled(bool checked);
    166   void onViewStatusBarActionToggled(bool checked);
    167   void onViewGameListActionTriggered();
    168   void onViewGameGridActionTriggered();
    169   void onViewSystemDisplayTriggered();
    170   void onViewGamePropertiesActionTriggered();
    171   void onGitHubRepositoryActionTriggered();
    172   void onIssueTrackerActionTriggered();
    173   void onDiscordServerActionTriggered();
    174   void onAboutActionTriggered();
    175   void onCheckForUpdatesActionTriggered();
    176   void onToolsMemoryCardEditorTriggered();
    177   void onToolsMemoryScannerTriggered();
    178   void onToolsCoverDownloaderTriggered();
    179   void onToolsMediaCaptureToggled(bool checked);
    180   void onToolsOpenDataDirectoryTriggered();
    181   void onSettingsTriggeredFromToolbar();
    182 
    183   void onGameListRefreshComplete();
    184   void onGameListRefreshProgress(const QString& status, int current, int total);
    185   void onGameListSelectionChanged();
    186   void onGameListEntryActivated();
    187   void onGameListEntryContextMenuRequested(const QPoint& point);
    188 
    189   void onUpdateCheckComplete();
    190 
    191   void openCheatManager();
    192   void openCPUDebugger();
    193 
    194 protected:
    195   void showEvent(QShowEvent* event) override;
    196   void closeEvent(QCloseEvent* event) override;
    197   void changeEvent(QEvent* event) override;
    198   void dragEnterEvent(QDragEnterEvent* event) override;
    199   void dropEvent(QDropEvent* event) override;
    200   void moveEvent(QMoveEvent* event) override;
    201   void resizeEvent(QResizeEvent* event) override;
    202 
    203 #ifdef _WIN32
    204   bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
    205 #endif
    206 
    207 private:
    208   /// Initializes the window. Call once at startup.
    209   void initialize();
    210 
    211   void setupAdditionalUi();
    212   void connectSignals();
    213 
    214   void updateEmulationActions(bool starting, bool running, bool cheevos_challenge_mode);
    215   void updateStatusBarWidgetVisibility();
    216   void updateWindowTitle();
    217   void updateWindowState(bool force_visible = false);
    218   void updateCheatActionsVisibility();
    219 
    220   void setProgressBar(int current, int total);
    221   void clearProgressBar();
    222 
    223   QWidget* getContentParent();
    224   QWidget* getDisplayContainer() const;
    225   bool isShowingGameList() const;
    226   bool isRenderingFullscreen() const;
    227   bool isRenderingToMain() const;
    228   bool shouldHideMouseCursor() const;
    229   bool shouldHideMainWindow() const;
    230 
    231   void switchToGameListView();
    232   void switchToEmulationView();
    233   void saveStateToConfig();
    234   void restoreStateFromConfig();
    235   void saveDisplayWindowGeometryToConfig();
    236   void restoreDisplayWindowGeometryFromConfig();
    237   void createDisplayWidget(bool fullscreen, bool render_to_main, bool use_main_window_pos);
    238   void destroyDisplayWidget(bool show_game_list);
    239   void updateDisplayWidgetCursor();
    240   void updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen);
    241 
    242   SettingsWindow* getSettingsWindow();
    243   void doSettings(const char* category = nullptr);
    244 
    245   ControllerSettingsWindow* getControllerSettingsWindow();
    246   void doControllerSettings(ControllerSettingsWindow::Category category = ControllerSettingsWindow::Category::Count);
    247 
    248   void updateDebugMenuCPUExecutionMode();
    249   void updateDebugMenuGPURenderer();
    250   void updateDebugMenuCropMode();
    251   std::string getDeviceDiscPath(const QString& title);
    252   void setGameListEntryCoverImage(const GameList::Entry* entry);
    253   void clearGameListEntryPlayTime(const GameList::Entry* entry);
    254   void updateTheme();
    255   void reloadThemeSpecificImages();
    256   void onSettingsThemeChanged();
    257   void destroySubWindows();
    258 
    259   void registerForDeviceNotifications();
    260   void unregisterForDeviceNotifications();
    261 
    262   /// Fills menu with save state info and handlers.
    263   void populateGameListContextMenu(const GameList::Entry* entry, QWidget* parent_window, QMenu* menu);
    264 
    265   void populateLoadStateMenu(const char* game_serial, QMenu* menu);
    266   void populateSaveStateMenu(const char* game_serial, QMenu* menu);
    267 
    268   /// Fills menu with the current playlist entries. The disc index is marked as checked.
    269   void populateChangeDiscSubImageMenu(QMenu* menu, QActionGroup* action_group);
    270 
    271   /// Fills menu with the current cheat options.
    272   void populateCheatsMenu(QMenu* menu);
    273 
    274   const GameList::Entry* resolveDiscSetEntry(const GameList::Entry* entry,
    275                                              std::unique_lock<std::recursive_mutex>& lock);
    276   std::shared_ptr<SystemBootParameters> getSystemBootParameters(std::string file);
    277   std::optional<bool> promptForResumeState(const std::string& save_state_path);
    278   void startFile(std::string path, std::optional<std::string> save_path, std::optional<bool> fast_boot);
    279   void startFileOrChangeDisc(const QString& path);
    280   void promptForDiscChange(const QString& path);
    281 
    282   Ui::MainWindow m_ui;
    283 
    284   GameListWidget* m_game_list_widget = nullptr;
    285 
    286   DisplayWidget* m_display_widget = nullptr;
    287   DisplayContainer* m_display_container = nullptr;
    288 
    289   QProgressBar* m_status_progress_widget = nullptr;
    290   QLabel* m_status_renderer_widget = nullptr;
    291   QLabel* m_status_fps_widget = nullptr;
    292   QLabel* m_status_vps_widget = nullptr;
    293   QLabel* m_status_resolution_widget = nullptr;
    294 
    295   QMenu* m_settings_toolbar_menu = nullptr;
    296 
    297   SettingsWindow* m_settings_window = nullptr;
    298   ControllerSettingsWindow* m_controller_settings_window = nullptr;
    299 
    300   AutoUpdaterDialog* m_auto_updater_dialog = nullptr;
    301   MemoryCardEditorWindow* m_memory_card_editor_window = nullptr;
    302   CheatManagerWindow* m_cheat_manager_window = nullptr;
    303   DebuggerWindow* m_debugger_window = nullptr;
    304   MemoryScannerWindow* m_memory_scanner_window = nullptr;
    305 
    306   bool m_was_paused_by_focus_loss = false;
    307   bool m_open_debugger_on_start = false;
    308   bool m_relative_mouse_mode = false;
    309   bool m_hide_mouse_cursor = false;
    310 
    311   bool m_display_created = false;
    312   bool m_save_states_invalidated = false;
    313   bool m_was_paused_on_surface_loss = false;
    314   bool m_was_disc_change_request = false;
    315   bool m_is_closing = false;
    316 
    317 #ifdef _WIN32
    318   void* m_device_notification_handle = nullptr;
    319 #endif
    320 };
    321 
    322 extern MainWindow* g_main_window;