Files
86Box/src/qt/qt_main.cpp

309 lines
9.9 KiB
C++
Raw Normal View History

2022-02-07 15:00:02 +06:00
/*
2023-01-06 15:36:05 -05:00
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
2022-02-07 15:00:02 +06:00
*
2023-01-06 15:36:05 -05:00
* This file is part of the 86Box distribution.
2022-02-07 15:00:02 +06:00
*
2023-01-06 15:36:05 -05:00
* Main entry point module
2022-02-07 15:00:02 +06:00
*
*
2023-01-06 15:36:05 -05:00
* Authors: Joakim L. Gilje <jgilje@jgilje.net>
2022-02-07 15:00:02 +06:00
* Cacodemon345
* Teemu Korhonen
*
2023-01-06 15:36:05 -05:00
* Copyright 2021 Joakim L. Gilje
* Copyright 2021-2022 Cacodemon345
* Copyright 2021-2022 Teemu Korhonen
2022-02-07 15:00:02 +06:00
*/
2021-11-25 10:20:56 +01:00
#include <QApplication>
#include <QSurfaceFormat>
2021-11-25 10:20:56 +01:00
#include <QDebug>
#include <QElapsedTimer>
#include <QThread>
#include <QTimer>
2021-12-31 12:36:55 +06:00
#include <QTranslator>
#include <QDirIterator>
#include <QLibraryInfo>
#include <QString>
2022-02-12 01:50:50 +06:00
#include <QFont>
2021-11-25 10:20:56 +01:00
2021-12-06 17:31:25 +02:00
#ifdef QT_STATIC
/* Static builds need plugin imports */
2022-11-19 08:49:04 -05:00
# include <QtPlugin>
2021-12-06 17:31:25 +02:00
Q_IMPORT_PLUGIN(QICOPlugin)
2022-11-19 08:49:04 -05:00
# ifdef Q_OS_WINDOWS
2021-12-06 17:31:25 +02:00
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin)
2022-11-19 08:49:04 -05:00
# endif
2021-12-06 17:31:25 +02:00
#endif
#ifdef Q_OS_WINDOWS
2022-11-19 08:49:04 -05:00
# include "qt_winrawinputfilter.hpp"
# include "qt_winmanagerfilter.hpp"
# include <86box/win.h>
# include <Shobjidl.h>
#endif
2022-11-19 08:49:04 -05:00
extern "C" {
2021-11-25 10:20:56 +01:00
#include <86box/86box.h>
#include <86box/config.h>
2021-11-25 10:20:56 +01:00
#include <86box/plat.h>
#include <86box/ui.h>
#include <86box/video.h>
#include <86box/discord.h>
2022-03-16 00:33:01 -03:00
#include <86box/gdbstub.h>
}
2021-11-25 10:20:56 +01:00
#include <thread>
2021-12-31 12:36:55 +06:00
#include <iostream>
#include <memory>
2021-11-25 10:20:56 +01:00
#include "qt_mainwindow.hpp"
2022-01-08 16:39:51 +06:00
#include "qt_progsettings.hpp"
#include "qt_settings.hpp"
#include "cocoa_mouse.hpp"
#include "qt_styleoverride.hpp"
#include "qt_unixmanagerfilter.hpp"
2022-02-15 02:34:13 +06:00
2021-11-25 10:20:56 +01:00
// Void Cast
2022-11-19 08:49:04 -05:00
#define VC(x) const_cast<wchar_t *>(x)
2021-11-25 10:20:56 +01:00
extern QElapsedTimer elapsed_timer;
2022-11-19 08:49:04 -05:00
extern MainWindow *main_window;
2021-11-25 10:20:56 +01:00
extern "C" {
2021-12-19 23:49:47 +02:00
#include <86box/timer.h>
#include <86box/nvr.h>
2022-11-19 08:49:04 -05:00
extern int qt_nvr_save(void);
2021-11-25 10:20:56 +01:00
}
void qt_set_sequence_auto_mnemonic(bool b);
2021-11-25 10:20:56 +01:00
void
main_thread_fn()
{
uint64_t old_time, new_time;
2022-11-19 08:49:04 -05:00
int drawits, frames;
2021-11-25 10:20:56 +01:00
QThread::currentThread()->setPriority(QThread::HighestPriority);
framecountx = 0;
2022-11-19 08:49:04 -05:00
// title_update = 1;
2021-11-25 10:20:56 +01:00
old_time = elapsed_timer.elapsed();
drawits = frames = 0;
while (!is_quit && cpu_thread_run) {
/* See if it is time to run a frame of code. */
new_time = elapsed_timer.elapsed();
2022-03-16 00:33:01 -03:00
#ifdef USE_GDBSTUB
if (gdbstub_next_asap && (drawits <= 0))
2022-11-19 08:49:04 -05:00
drawits = 10;
2022-03-16 00:33:01 -03:00
else
#endif
2022-11-19 08:49:04 -05:00
drawits += (new_time - old_time);
2021-11-25 10:20:56 +01:00
old_time = new_time;
if (drawits > 0 && !dopause) {
/* Yes, so do one frame now. */
drawits -= 10;
if (drawits > 50)
drawits = 0;
#ifdef USE_INSTRUMENT
uint64_t start_time = elapsed_timer.nsecsElapsed();
#endif
2021-11-25 10:20:56 +01:00
/* Run a block of code. */
pc_run();
#ifdef USE_INSTRUMENT
if (instru_enabled) {
2022-11-19 08:49:04 -05:00
uint64_t elapsed_us = (elapsed_timer.nsecsElapsed() - start_time) / 1000;
uint64_t total_elapsed_ms = (uint64_t) ((double) tsc / cpu_s->rspeed * 1000);
2022-08-06 14:51:42 +02:00
printf("[instrument] %llu, %llu\n", total_elapsed_ms, elapsed_us);
if (instru_run_ms && total_elapsed_ms >= instru_run_ms)
break;
}
#endif
2021-11-25 10:20:56 +01:00
/* Every 200 frames we save the machine status. */
if (++frames >= 200 && nvr_dosave) {
qt_nvr_save();
nvr_dosave = 0;
2022-11-19 08:49:04 -05:00
frames = 0;
2021-11-25 10:20:56 +01:00
}
} else {
/* Just so we dont overload the host OS. */
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
2021-11-25 10:20:56 +01:00
}
is_quit = 1;
2022-11-19 08:49:04 -05:00
QTimer::singleShot(0, QApplication::instance(), []() { QApplication::instance()->quit(); });
2021-11-25 10:20:56 +01:00
}
2022-11-19 08:49:04 -05:00
static std::thread *main_thread;
2022-07-04 01:50:42 +06:00
2022-11-19 08:49:04 -05:00
int
main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2022-02-09 20:57:58 +06:00
QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, false);
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
QApplication app(argc, argv);
QLocale::setDefault(QLocale::C);
qt_set_sequence_auto_mnemonic(false);
2021-12-31 12:36:55 +06:00
Q_INIT_RESOURCE(qt_resources);
Q_INIT_RESOURCE(qt_translations);
QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
fmt.setSwapInterval(0);
QSurfaceFormat::setDefaultFormat(fmt);
app.setStyle(new StyleOverride());
2022-01-08 16:39:51 +06:00
#ifdef __APPLE__
CocoaEventFilter cocoafilter;
app.installNativeEventFilter(&cocoafilter);
#endif
2021-11-25 10:20:56 +01:00
elapsed_timer.start();
2022-11-19 08:49:04 -05:00
if (!pc_init(argc, argv)) {
return 0;
}
bool startMaximized = window_remember && monitor_settings[0].mon_window_maximized;
fprintf(stderr, "Qt: version %s, platform \"%s\"\n", qVersion(), QApplication::platformName().toUtf8().data());
2022-01-08 16:39:51 +06:00
ProgSettings::loadTranslators(&app);
#ifdef Q_OS_WINDOWS
auto font_name = QObject::tr("FONT_NAME");
auto font_size = QObject::tr("FONT_SIZE");
QApplication::setFont(QFont(font_name, font_size.toInt()));
SetCurrentProcessExplicitAppUserModelID(L"86Box.86Box");
#endif
2022-11-19 08:49:04 -05:00
if (!pc_init_modules()) {
ui_msgbox_header(MBX_FATAL, (void *) IDS_2121, (void *) IDS_2056);
return 6;
}
2021-11-25 10:20:56 +01:00
2022-11-19 08:49:04 -05:00
if (settings_only) {
Settings settings;
2022-11-19 08:49:04 -05:00
if (settings.exec() == QDialog::Accepted) {
settings.save();
config_save();
}
return 0;
}
discord_load();
2021-11-29 12:25:27 +01:00
main_window = new MainWindow();
if (startMaximized) {
main_window->showMaximized();
} else {
main_window->show();
}
2021-12-05 15:57:46 +06:00
app.installEventFilter(main_window);
#ifdef Q_OS_WINDOWS
/* Setup VM-manager messages */
std::unique_ptr<WindowsManagerFilter> wmfilter;
2022-11-19 08:49:04 -05:00
if (source_hwnd) {
HWND main_hwnd = (HWND) main_window->winId();
wmfilter.reset(new WindowsManagerFilter());
2022-01-22 12:40:15 +02:00
QObject::connect(wmfilter.get(), &WindowsManagerFilter::showsettings, main_window, &MainWindow::showSettings);
QObject::connect(wmfilter.get(), &WindowsManagerFilter::pause, main_window, &MainWindow::togglePause);
QObject::connect(wmfilter.get(), &WindowsManagerFilter::reset, main_window, &MainWindow::hardReset);
QObject::connect(wmfilter.get(), &WindowsManagerFilter::request_shutdown, main_window, &MainWindow::close);
2022-11-19 08:49:04 -05:00
QObject::connect(wmfilter.get(), &WindowsManagerFilter::force_shutdown, []() {
do_stop();
emit main_window->close();
});
2022-11-19 08:49:04 -05:00
QObject::connect(wmfilter.get(), &WindowsManagerFilter::ctrlaltdel, []() { pc_send_cad(); });
QObject::connect(wmfilter.get(), &WindowsManagerFilter::dialogstatus, [main_hwnd](bool open) {
PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDDLGSTATUS, (WPARAM) (open ? 1 : 0), (LPARAM) main_hwnd);
});
/* Native filter to catch VM-managers commands */
app.installNativeEventFilter(wmfilter.get());
/* Filter to catch main window being blocked (by modal dialog) */
main_window->installEventFilter(wmfilter.get());
/* Send main window HWND to manager */
2022-11-19 08:49:04 -05:00
PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDHWND, (WPARAM) unique_id, (LPARAM) main_hwnd);
/* Send shutdown message to manager */
2022-11-19 08:49:04 -05:00
QObject::connect(&app, &QApplication::destroyed, [main_hwnd](QObject *) {
PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) main_hwnd);
});
}
/* Setup raw input */
auto rawInputFilter = WindowsRawInputFilter::Register(main_window);
2022-11-19 08:49:04 -05:00
if (rawInputFilter) {
app.installNativeEventFilter(rawInputFilter.get());
QObject::disconnect(main_window, &MainWindow::pollMouse, 0, 0);
2022-11-19 08:49:04 -05:00
QObject::connect(main_window, &MainWindow::pollMouse, (WindowsRawInputFilter *) rawInputFilter.get(), &WindowsRawInputFilter::mousePoll, Qt::DirectConnection);
main_window->setSendKeyboardInput(false);
2022-02-20 02:26:27 -05:00
}
#endif
UnixManagerSocket socket;
2022-11-19 08:49:04 -05:00
if (qgetenv("86BOX_MANAGER_SOCKET").size()) {
QObject::connect(&socket, &UnixManagerSocket::showsettings, main_window, &MainWindow::showSettings);
QObject::connect(&socket, &UnixManagerSocket::pause, main_window, &MainWindow::togglePause);
QObject::connect(&socket, &UnixManagerSocket::resetVM, main_window, &MainWindow::hardReset);
QObject::connect(&socket, &UnixManagerSocket::request_shutdown, main_window, &MainWindow::close);
2022-11-19 08:49:04 -05:00
QObject::connect(&socket, &UnixManagerSocket::force_shutdown, []() {
do_stop();
emit main_window->close();
});
2022-11-19 08:49:04 -05:00
QObject::connect(&socket, &UnixManagerSocket::ctrlaltdel, []() { pc_send_cad(); });
main_window->installEventFilter(&socket);
socket.connectToServer(qgetenv("86BOX_MANAGER_SOCKET"));
}
2022-11-19 08:49:04 -05:00
// pc_reset_hard_init();
2021-11-25 10:20:56 +01:00
/* Set the PAUSE mode depending on the renderer. */
// plat_pause(0);
QTimer onesec;
QTimer discordupdate;
QObject::connect(&onesec, &QTimer::timeout, &app, [] {
pc_onesec();
});
onesec.setTimerType(Qt::PreciseTimer);
onesec.start(1000);
if (discord_loaded) {
QTimer::singleShot(1000, &app, [] {
if (enable_discord) {
discord_init();
discord_update_activity(dopause);
} else
discord_close();
});
QObject::connect(&discordupdate, &QTimer::timeout, &app, [] {
discord_run_callbacks();
});
discordupdate.start(1000);
}
2021-11-25 10:20:56 +01:00
/* Initialize the rendering window, or fullscreen. */
2022-11-19 08:49:04 -05:00
QTimer::singleShot(0, &app, [] {
2022-07-04 01:50:42 +06:00
pc_reset_hard_init();
main_thread = new std::thread(main_thread_fn);
2021-11-25 10:20:56 +01:00
});
2022-11-19 08:49:04 -05:00
auto ret = app.exec();
2021-11-25 10:20:56 +01:00
cpu_thread_run = 0;
2022-07-04 01:50:42 +06:00
main_thread->join();
pc_close(nullptr);
endblit();
2021-11-25 10:20:56 +01:00
socket.close();
2021-11-25 10:20:56 +01:00
return ret;
}